xml.browser.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. // Copyright (c) Microsoft Corporation. All rights reserved.
  2. // Licensed under the MIT License. See License.txt in the project root for license information.
  3. var parser = new DOMParser();
  4. export function parseXML(str) {
  5. try {
  6. var dom = parser.parseFromString(str, "application/xml");
  7. throwIfError(dom);
  8. var obj = domToObject(dom.childNodes[0]);
  9. return Promise.resolve(obj);
  10. }
  11. catch (err) {
  12. return Promise.reject(err);
  13. }
  14. }
  15. var errorNS = "";
  16. try {
  17. errorNS = parser.parseFromString("INVALID", "text/xml").getElementsByTagName("parsererror")[0].namespaceURI;
  18. }
  19. catch (ignored) {
  20. // Most browsers will return a document containing <parsererror>, but IE will throw.
  21. }
  22. function throwIfError(dom) {
  23. if (errorNS) {
  24. var parserErrors = dom.getElementsByTagNameNS(errorNS, "parsererror");
  25. if (parserErrors.length) {
  26. throw new Error(parserErrors.item(0).innerHTML);
  27. }
  28. }
  29. }
  30. function isElement(node) {
  31. return !!node.attributes;
  32. }
  33. /**
  34. * Get the Element-typed version of the provided Node if the provided node is an element with
  35. * attributes. If it isn't, then undefined is returned.
  36. */
  37. function asElementWithAttributes(node) {
  38. return isElement(node) && node.hasAttributes() ? node : undefined;
  39. }
  40. function domToObject(node) {
  41. var result = {};
  42. var childNodeCount = node.childNodes.length;
  43. var firstChildNode = node.childNodes[0];
  44. var onlyChildTextValue = (firstChildNode && childNodeCount === 1 && firstChildNode.nodeType === Node.TEXT_NODE && firstChildNode.nodeValue) || undefined;
  45. var elementWithAttributes = asElementWithAttributes(node);
  46. if (elementWithAttributes) {
  47. result["$"] = {};
  48. for (var i = 0; i < elementWithAttributes.attributes.length; i++) {
  49. var attr = elementWithAttributes.attributes[i];
  50. result["$"][attr.nodeName] = attr.nodeValue;
  51. }
  52. if (onlyChildTextValue) {
  53. result["_"] = onlyChildTextValue;
  54. }
  55. }
  56. else if (childNodeCount === 0) {
  57. result = "";
  58. }
  59. else if (onlyChildTextValue) {
  60. result = onlyChildTextValue;
  61. }
  62. if (!onlyChildTextValue) {
  63. for (var i = 0; i < childNodeCount; i++) {
  64. var child = node.childNodes[i];
  65. // Ignore leading/trailing whitespace nodes
  66. if (child.nodeType !== Node.TEXT_NODE) {
  67. var childObject = domToObject(child);
  68. if (!result[child.nodeName]) {
  69. result[child.nodeName] = childObject;
  70. }
  71. else if (Array.isArray(result[child.nodeName])) {
  72. result[child.nodeName].push(childObject);
  73. }
  74. else {
  75. result[child.nodeName] = [result[child.nodeName], childObject];
  76. }
  77. }
  78. }
  79. }
  80. return result;
  81. }
  82. // tslint:disable-next-line:no-null-keyword
  83. var doc = document.implementation.createDocument(null, null, null);
  84. var serializer = new XMLSerializer();
  85. export function stringifyXML(obj, opts) {
  86. var rootName = opts && opts.rootName || "root";
  87. var dom = buildNode(obj, rootName)[0];
  88. return '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' + serializer.serializeToString(dom);
  89. }
  90. function buildAttributes(attrs) {
  91. var result = [];
  92. for (var _i = 0, _a = Object.keys(attrs); _i < _a.length; _i++) {
  93. var key = _a[_i];
  94. var attr = doc.createAttribute(key);
  95. attr.value = attrs[key].toString();
  96. result.push(attr);
  97. }
  98. return result;
  99. }
  100. function buildNode(obj, elementName) {
  101. if (typeof obj === "string" || typeof obj === "number" || typeof obj === "boolean") {
  102. var elem = doc.createElement(elementName);
  103. elem.textContent = obj.toString();
  104. return [elem];
  105. }
  106. else if (Array.isArray(obj)) {
  107. var result = [];
  108. for (var _i = 0, obj_1 = obj; _i < obj_1.length; _i++) {
  109. var arrayElem = obj_1[_i];
  110. for (var _a = 0, _b = buildNode(arrayElem, elementName); _a < _b.length; _a++) {
  111. var child = _b[_a];
  112. result.push(child);
  113. }
  114. }
  115. return result;
  116. }
  117. else if (typeof obj === "object") {
  118. var elem = doc.createElement(elementName);
  119. for (var _c = 0, _d = Object.keys(obj); _c < _d.length; _c++) {
  120. var key = _d[_c];
  121. if (key === "$") {
  122. for (var _e = 0, _f = buildAttributes(obj[key]); _e < _f.length; _e++) {
  123. var attr = _f[_e];
  124. elem.attributes.setNamedItem(attr);
  125. }
  126. }
  127. else {
  128. for (var _g = 0, _h = buildNode(obj[key], key); _g < _h.length; _g++) {
  129. var child = _h[_g];
  130. elem.appendChild(child);
  131. }
  132. }
  133. }
  134. return [elem];
  135. }
  136. else {
  137. throw new Error("Illegal value passed to buildObject: " + obj);
  138. }
  139. }
  140. //# sourceMappingURL=xml.browser.js.map