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