Back to index

lightning-sunbird  0.9+nobinonly
XMLUtils.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is TransforMiiX XSLT processor code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * The MITRE Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1999
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Keith Visco <kvisco@ziplink.net> (Original Author)
00024  *   Lidong <lidong520@263.net>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either the GNU General Public License Version 2 or later (the "GPL"), or
00028  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 /*
00041  * XML utility classes
00042  */
00043 
00044 #include "XMLUtils.h"
00045 #include "nsString.h"
00046 #include "nsReadableUtils.h"
00047 #include "txAtoms.h"
00048 #include "txStringUtils.h"
00049 #include "txNamespaceMap.h"
00050 #include "txXPathTreeWalker.h"
00051 
00052 nsresult
00053 txExpandedName::init(const nsAString& aQName, txNamespaceMap* aResolver,
00054                      MBool aUseDefault)
00055 {
00056     const nsAFlatString& qName = PromiseFlatString(aQName);
00057     const PRUnichar* colon;
00058     PRBool valid = XMLUtils::isValidQName(qName, &colon);
00059     if (!valid) {
00060         return NS_ERROR_FAILURE;
00061     }
00062 
00063     if (colon) {
00064         nsCOMPtr<nsIAtom> prefix = do_GetAtom(Substring(qName.get(), colon));
00065         PRInt32 namespaceID = aResolver->lookupNamespace(prefix);
00066         if (namespaceID == kNameSpaceID_Unknown)
00067             return NS_ERROR_FAILURE;
00068         mNamespaceID = namespaceID;
00069 
00070         const PRUnichar *end;
00071         qName.EndReading(end);
00072         mLocalName = do_GetAtom(Substring(colon + 1, end));
00073     }
00074     else {
00075         mNamespaceID = aUseDefault ? aResolver->lookupNamespace(nsnull) :
00076                                      kNameSpaceID_None;
00077         mLocalName = do_GetAtom(aQName);
00078     }
00079     return NS_OK;
00080 }
00081 
00082   //------------------------------/
00083  //- Implementation of XMLUtils -/
00084 //------------------------------/
00085 
00086 // static
00087 nsresult
00088 XMLUtils::splitExpatName(const PRUnichar *aExpatName, nsIAtom **aPrefix,
00089                          nsIAtom **aLocalName, PRInt32* aNameSpaceID)
00090 {
00101     const PRUnichar *uriEnd = nsnull;
00102     const PRUnichar *nameEnd = nsnull;
00103     const PRUnichar *pos;
00104     for (pos = aExpatName; *pos; ++pos) {
00105         if (*pos == 0xFFFF) {
00106             if (uriEnd) {
00107                 nameEnd = pos;
00108             }
00109             else {
00110                 uriEnd = pos;
00111             }
00112         }
00113     }
00114 
00115     const PRUnichar *nameStart;
00116     if (uriEnd) {
00117         *aNameSpaceID =
00118             txNamespaceManager::getNamespaceID(nsDependentSubstring(aExpatName,
00119                                                                     uriEnd));
00120         if (*aNameSpaceID == kNameSpaceID_Unknown) {
00121             return NS_ERROR_FAILURE;
00122         }
00123 
00124         nameStart = (uriEnd + 1);
00125         if (nameEnd)  {
00126             const PRUnichar *prefixStart = nameEnd + 1;
00127             *aPrefix = NS_NewAtom(NS_ConvertUTF16toUTF8(prefixStart,
00128                                                         pos - prefixStart));
00129             if (!*aPrefix) {
00130                 return NS_ERROR_OUT_OF_MEMORY;
00131             }
00132         }
00133         else {
00134             nameEnd = pos;
00135             *aPrefix = nsnull;
00136         }
00137     }
00138     else {
00139         *aNameSpaceID = kNameSpaceID_None;
00140         nameStart = aExpatName;
00141         nameEnd = pos;
00142         *aPrefix = nsnull;
00143     }
00144 
00145     *aLocalName = NS_NewAtom(NS_ConvertUTF16toUTF8(nameStart,
00146                                                    nameEnd - nameStart));
00147 
00148     return *aLocalName ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
00149 }
00150 
00151 nsresult
00152 XMLUtils::splitQName(const nsAString& aName, nsIAtom** aPrefix,
00153                      nsIAtom** aLocalName)
00154 {
00155     const nsAFlatString& qName = PromiseFlatString(aName);
00156     const PRUnichar* colon;
00157     PRBool valid = XMLUtils::isValidQName(qName, &colon);
00158     if (!valid) {
00159         return NS_ERROR_FAILURE;
00160     }
00161 
00162     if (colon) {
00163         const PRUnichar *end;
00164         qName.EndReading(end);
00165 
00166         *aPrefix = NS_NewAtom(Substring(qName.get(), colon));
00167         *aLocalName = NS_NewAtom(Substring(colon + 1, end));
00168     }
00169     else {
00170         *aPrefix = nsnull;
00171         *aLocalName = NS_NewAtom(aName);
00172     }
00173 
00174     return NS_OK;
00175 }
00176 
00177 const nsDependentSubstring XMLUtils::getLocalPart(const nsAString& src)
00178 {
00179     // Anything after ':' is the local part of the name
00180     PRInt32 idx = src.FindChar(':');
00181     if (idx == kNotFound) {
00182         return Substring(src, 0, src.Length());
00183     }
00184 
00185     NS_ASSERTION(idx > 0, "This QName looks invalid.");
00186     return Substring(src, idx + 1, src.Length() - (idx + 1));
00187 }
00188 
00192 PRBool XMLUtils::isWhitespace(const nsAFlatString& aText)
00193 {
00194     nsAFlatString::const_char_iterator start, end;
00195     aText.BeginReading(start);
00196     aText.EndReading(end);
00197     for ( ; start != end; ++start) {
00198         if (!isWhitespace(*start)) {
00199             return PR_FALSE;
00200         }
00201     }
00202     return PR_TRUE;
00203 }
00204 
00208 void XMLUtils::normalizePIValue(nsAString& piValue)
00209 {
00210     nsAutoString origValue(piValue);
00211     PRUint32 origLength = origValue.Length();
00212     PRUint32 conversionLoop = 0;
00213     PRUnichar prevCh = 0;
00214     piValue.Truncate();
00215 
00216     while (conversionLoop < origLength) {
00217         PRUnichar ch = origValue.CharAt(conversionLoop);
00218         switch (ch) {
00219             case '>':
00220             {
00221                 if (prevCh == '?') {
00222                     piValue.Append(PRUnichar(' '));
00223                 }
00224                 break;
00225             }
00226             default:
00227             {
00228                 break;
00229             }
00230         }
00231         piValue.Append(ch);
00232         prevCh = ch;
00233         ++conversionLoop;
00234     }
00235 }
00236 
00237 //static
00238 MBool XMLUtils::getXMLSpacePreserve(const txXPathNode& aNode)
00239 {
00240     nsAutoString value;
00241     txXPathTreeWalker walker(aNode);
00242     do {
00243         if (walker.getAttr(txXMLAtoms::space, kNameSpaceID_XML, value)) {
00244             if (TX_StringEqualsAtom(value, txXMLAtoms::preserve)) {
00245                 return PR_TRUE;
00246             }
00247             if (TX_StringEqualsAtom(value, txXMLAtoms::_default)) {
00248                 return PR_FALSE;
00249             }
00250         }
00251     } while (walker.moveToParent());
00252 
00253     return PR_FALSE;
00254 }