Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : /*
7 : * XML utility classes
8 : */
9 :
10 : #include "txXMLUtils.h"
11 : #include "nsString.h"
12 : #include "nsReadableUtils.h"
13 : #include "nsGkAtoms.h"
14 : #include "txStringUtils.h"
15 : #include "txNamespaceMap.h"
16 : #include "txXPathTreeWalker.h"
17 : #include "nsContentUtils.h"
18 :
19 : //------------------------------/
20 : //- Implementation of XMLUtils -/
21 : //------------------------------/
22 :
23 : // static
24 : nsresult
25 0 : XMLUtils::splitExpatName(const char16_t *aExpatName, nsIAtom **aPrefix,
26 : nsIAtom **aLocalName, int32_t* aNameSpaceID)
27 : {
28 : /**
29 : * Expat can send the following:
30 : * localName
31 : * namespaceURI<separator>localName
32 : * namespaceURI<separator>localName<separator>prefix
33 : */
34 :
35 0 : const char16_t *uriEnd = nullptr;
36 0 : const char16_t *nameEnd = nullptr;
37 : const char16_t *pos;
38 0 : for (pos = aExpatName; *pos; ++pos) {
39 0 : if (*pos == kExpatSeparatorChar) {
40 0 : if (uriEnd) {
41 0 : nameEnd = pos;
42 : }
43 : else {
44 0 : uriEnd = pos;
45 : }
46 : }
47 : }
48 :
49 : const char16_t *nameStart;
50 0 : if (uriEnd) {
51 0 : *aNameSpaceID =
52 0 : txNamespaceManager::getNamespaceID(nsDependentSubstring(aExpatName,
53 : uriEnd));
54 0 : if (*aNameSpaceID == kNameSpaceID_Unknown) {
55 0 : return NS_ERROR_FAILURE;
56 : }
57 :
58 0 : nameStart = (uriEnd + 1);
59 0 : if (nameEnd) {
60 0 : const char16_t *prefixStart = nameEnd + 1;
61 0 : *aPrefix = NS_Atomize(Substring(prefixStart, pos)).take();
62 0 : if (!*aPrefix) {
63 0 : return NS_ERROR_OUT_OF_MEMORY;
64 : }
65 : }
66 : else {
67 0 : nameEnd = pos;
68 0 : *aPrefix = nullptr;
69 : }
70 : }
71 : else {
72 0 : *aNameSpaceID = kNameSpaceID_None;
73 0 : nameStart = aExpatName;
74 0 : nameEnd = pos;
75 0 : *aPrefix = nullptr;
76 : }
77 :
78 0 : *aLocalName = NS_Atomize(Substring(nameStart, nameEnd)).take();
79 :
80 0 : return *aLocalName ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
81 : }
82 :
83 : nsresult
84 0 : XMLUtils::splitQName(const nsAString& aName, nsIAtom** aPrefix,
85 : nsIAtom** aLocalName)
86 : {
87 0 : const nsString& qName = PromiseFlatString(aName);
88 : const char16_t* colon;
89 0 : bool valid = XMLUtils::isValidQName(qName, &colon);
90 0 : if (!valid) {
91 0 : return NS_ERROR_FAILURE;
92 : }
93 :
94 0 : if (colon) {
95 : const char16_t *end;
96 0 : qName.EndReading(end);
97 :
98 0 : *aPrefix = NS_Atomize(Substring(qName.get(), colon)).take();
99 0 : *aLocalName = NS_Atomize(Substring(colon + 1, end)).take();
100 : }
101 : else {
102 0 : *aPrefix = nullptr;
103 0 : *aLocalName = NS_Atomize(aName).take();
104 : }
105 :
106 0 : return NS_OK;
107 : }
108 :
109 : /**
110 : * Returns true if the given string has only whitespace characters
111 : */
112 0 : bool XMLUtils::isWhitespace(const nsString& aText)
113 : {
114 : nsString::const_char_iterator start, end;
115 0 : aText.BeginReading(start);
116 0 : aText.EndReading(end);
117 0 : for ( ; start != end; ++start) {
118 0 : if (!isWhitespace(*start)) {
119 0 : return false;
120 : }
121 : }
122 0 : return true;
123 : }
124 :
125 : /**
126 : * Normalizes the value of a XML processing instruction
127 : **/
128 0 : void XMLUtils::normalizePIValue(nsAString& piValue)
129 : {
130 0 : nsAutoString origValue(piValue);
131 0 : uint32_t origLength = origValue.Length();
132 0 : uint32_t conversionLoop = 0;
133 0 : char16_t prevCh = 0;
134 0 : piValue.Truncate();
135 :
136 0 : while (conversionLoop < origLength) {
137 0 : char16_t ch = origValue.CharAt(conversionLoop);
138 0 : switch (ch) {
139 : case '>':
140 : {
141 0 : if (prevCh == '?') {
142 0 : piValue.Append(char16_t(' '));
143 : }
144 0 : break;
145 : }
146 : default:
147 : {
148 0 : break;
149 : }
150 : }
151 0 : piValue.Append(ch);
152 0 : prevCh = ch;
153 0 : ++conversionLoop;
154 : }
155 0 : }
156 :
157 : //static
158 0 : bool XMLUtils::isValidQName(const nsString& aQName, const char16_t** aColon)
159 : {
160 0 : return NS_SUCCEEDED(nsContentUtils::CheckQName(aQName, true, aColon));
161 : }
162 :
163 : //static
164 0 : bool XMLUtils::getXMLSpacePreserve(const txXPathNode& aNode)
165 : {
166 0 : nsAutoString value;
167 0 : txXPathTreeWalker walker(aNode);
168 0 : do {
169 0 : if (walker.getAttr(nsGkAtoms::space, kNameSpaceID_XML, value)) {
170 0 : if (TX_StringEqualsAtom(value, nsGkAtoms::preserve)) {
171 0 : return true;
172 : }
173 0 : if (TX_StringEqualsAtom(value, nsGkAtoms::_default)) {
174 0 : return false;
175 : }
176 : }
177 : } while (walker.moveToParent());
178 :
179 0 : return false;
180 : }
|