txXMLUtils.cpp 4.7 KB

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