Bug 570258: Some more atom usage cleanup. r=jst
[mozilla-central.git] / content / xslt / src / xml / txXMLUtils.cpp
blob79c359bb081ea2af2dd81fbce6077c3c6c1c9271
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is TransforMiiX XSLT processor code.
17 * The Initial Developer of the Original Code is
18 * The MITRE Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1999
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
23 * Keith Visco <kvisco@ziplink.net> (Original Author)
24 * Lidong <lidong520@263.net>
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
41 * XML utility classes
44 #include "txXMLUtils.h"
45 #include "nsString.h"
46 #include "nsReadableUtils.h"
47 #include "txAtoms.h"
48 #include "txStringUtils.h"
49 #include "txNamespaceMap.h"
50 #include "txXPathTreeWalker.h"
52 nsresult
53 txExpandedName::init(const nsAString& aQName, txNamespaceMap* aResolver,
54 MBool aUseDefault)
56 const nsAFlatString& qName = PromiseFlatString(aQName);
57 const PRUnichar* colon;
58 PRBool valid = XMLUtils::isValidQName(qName, &colon);
59 if (!valid) {
60 return NS_ERROR_FAILURE;
63 if (colon) {
64 nsCOMPtr<nsIAtom> prefix = do_GetAtom(Substring(qName.get(), colon));
65 PRInt32 namespaceID = aResolver->lookupNamespace(prefix);
66 if (namespaceID == kNameSpaceID_Unknown)
67 return NS_ERROR_FAILURE;
68 mNamespaceID = namespaceID;
70 const PRUnichar *end;
71 qName.EndReading(end);
72 mLocalName = do_GetAtom(Substring(colon + 1, end));
74 else {
75 mNamespaceID = aUseDefault ? aResolver->lookupNamespace(nsnull) :
76 kNameSpaceID_None;
77 mLocalName = do_GetAtom(aQName);
79 return NS_OK;
82 //------------------------------/
83 //- Implementation of XMLUtils -/
84 //------------------------------/
86 // static
87 nsresult
88 XMLUtils::splitExpatName(const PRUnichar *aExpatName, nsIAtom **aPrefix,
89 nsIAtom **aLocalName, PRInt32* aNameSpaceID)
91 /**
92 * Expat can send the following:
93 * localName
94 * namespaceURI<separator>localName
95 * namespaceURI<separator>localName<separator>prefix
98 const PRUnichar *uriEnd = nsnull;
99 const PRUnichar *nameEnd = nsnull;
100 const PRUnichar *pos;
101 for (pos = aExpatName; *pos; ++pos) {
102 if (*pos == kExpatSeparatorChar) {
103 if (uriEnd) {
104 nameEnd = pos;
106 else {
107 uriEnd = pos;
112 const PRUnichar *nameStart;
113 if (uriEnd) {
114 *aNameSpaceID =
115 txNamespaceManager::getNamespaceID(nsDependentSubstring(aExpatName,
116 uriEnd));
117 if (*aNameSpaceID == kNameSpaceID_Unknown) {
118 return NS_ERROR_FAILURE;
121 nameStart = (uriEnd + 1);
122 if (nameEnd) {
123 const PRUnichar *prefixStart = nameEnd + 1;
124 *aPrefix = NS_NewAtom(Substring(prefixStart, pos));
125 if (!*aPrefix) {
126 return NS_ERROR_OUT_OF_MEMORY;
129 else {
130 nameEnd = pos;
131 *aPrefix = nsnull;
134 else {
135 *aNameSpaceID = kNameSpaceID_None;
136 nameStart = aExpatName;
137 nameEnd = pos;
138 *aPrefix = nsnull;
141 *aLocalName = NS_NewAtom(Substring(nameStart, nameEnd));
143 return *aLocalName ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
146 nsresult
147 XMLUtils::splitQName(const nsAString& aName, nsIAtom** aPrefix,
148 nsIAtom** aLocalName)
150 const nsAFlatString& qName = PromiseFlatString(aName);
151 const PRUnichar* colon;
152 PRBool valid = XMLUtils::isValidQName(qName, &colon);
153 if (!valid) {
154 return NS_ERROR_FAILURE;
157 if (colon) {
158 const PRUnichar *end;
159 qName.EndReading(end);
161 *aPrefix = NS_NewAtom(Substring(qName.get(), colon));
162 *aLocalName = NS_NewAtom(Substring(colon + 1, end));
164 else {
165 *aPrefix = nsnull;
166 *aLocalName = NS_NewAtom(aName);
169 return NS_OK;
172 const nsDependentSubstring XMLUtils::getLocalPart(const nsAString& src)
174 // Anything after ':' is the local part of the name
175 PRInt32 idx = src.FindChar(':');
176 if (idx == kNotFound) {
177 return Substring(src, 0, src.Length());
180 NS_ASSERTION(idx > 0, "This QName looks invalid.");
181 return Substring(src, idx + 1, src.Length() - (idx + 1));
185 * Returns true if the given string has only whitespace characters
187 PRBool XMLUtils::isWhitespace(const nsAFlatString& aText)
189 nsAFlatString::const_char_iterator start, end;
190 aText.BeginReading(start);
191 aText.EndReading(end);
192 for ( ; start != end; ++start) {
193 if (!isWhitespace(*start)) {
194 return PR_FALSE;
197 return PR_TRUE;
201 * Normalizes the value of a XML processing instruction
203 void XMLUtils::normalizePIValue(nsAString& piValue)
205 nsAutoString origValue(piValue);
206 PRUint32 origLength = origValue.Length();
207 PRUint32 conversionLoop = 0;
208 PRUnichar prevCh = 0;
209 piValue.Truncate();
211 while (conversionLoop < origLength) {
212 PRUnichar ch = origValue.CharAt(conversionLoop);
213 switch (ch) {
214 case '>':
216 if (prevCh == '?') {
217 piValue.Append(PRUnichar(' '));
219 break;
221 default:
223 break;
226 piValue.Append(ch);
227 prevCh = ch;
228 ++conversionLoop;
232 //static
233 MBool XMLUtils::getXMLSpacePreserve(const txXPathNode& aNode)
235 nsAutoString value;
236 txXPathTreeWalker walker(aNode);
237 do {
238 if (walker.getAttr(txXMLAtoms::space, kNameSpaceID_XML, value)) {
239 if (TX_StringEqualsAtom(value, txXMLAtoms::preserve)) {
240 return PR_TRUE;
242 if (TX_StringEqualsAtom(value, txXMLAtoms::_default)) {
243 return PR_FALSE;
246 } while (walker.moveToParent());
248 return PR_FALSE;