我有一个
XML片段,我解析使用jQuery parseXML.大多数节点没有前缀,它们在默认命名空间中,有些具有前缀.
我需要将默认命名空间中的所有节点与前缀相关联.我已经确保这个前缀已经在XML的字符串版本中被声明,并且使用了一个神奇的字符串替换(即xmlns:my =“http://mydefaulns.com”在加载XML时在根级别被声明. )
我试过以下:
var defaultNs="http://mydefaulns.com"; var xmlDoc = $.parseXML(stringXML); $(xmlDoc).find("*").each(function() { if (this.namespaceURI=== defaultNs) { this.prefix = "my"; } }
但是它没有任何影响,当我写回XML还是没有前缀的时候.
我也试图加载XML并调用:
xmlDoc.firstChild.removeAttribute("xmlns")
在这一点上,我认为获得我想要的结果的唯一方法是使用新的前缀名重新创建所有节点,复制所有属性.
这看起来真的很极端,还有另一种方式吗?
输入(字符串):
<abc xmlns="http://mydefaulns.com" xmlns:my="http://mydefaulns.com"xmlns:other="http://other.com"> <node1>Value</node1> <other:node2>Value2</other:node2> </abc>
所需输出:
<my:abc xmlns:my="http://mydefaulns.com"xmlns:other="http://other.com"> <my:node1>Value</my:node1> <other:node2>Value2</other:node2> </my:abc>
实际的XML更复杂,但这给你一个想法.
我用jQuery.parse解析XML,并通过使用来获取字符串版本
function XMLDocumentToString(oXML) { if (typeof oXML.xml != "undefined") { return oXML.xml; } else if (XMLSerializer) { return (new XMLSerializer().serializeToString(oXML)); } else { throw "Unable to serialize the XML"; } }
解决方法
At that point,I think the only way to get the result that I want would be to recreate all the nodes with the new prefixed name,copying all the attributes.
是的,如果你想干净地做,那就是你要做的事情.
使用正则表达式的解决方案是脆弱的.这是你给出的例子:
<abc xmlns="http://mydefaulns.com" xmlns:my="http://mydefaulns.com" xmlns:other="http://other.com"> <node1>Value</node1> <other:node2>Value2</other:node2> </abc>
<abc xmlns="http://mydefaulns.com" xmlns:my="http://mydefaulns.com"> <node1>Value</node1> <node2 xmlns="http://other.com">Value2</node2> </abc>
唯一改变的是在命名空间http://other.com中的元素node2被分配了一个命名空间.在您的原始文档中,它是通过在根节点上定义的另一个前缀.这是通过重新定义node2上的默认命名空间.从XML的角度来看,这两个文档是一样的.如何定义node2的命名空间并不重要.问题是,您获得的两个基于正则表达式的答案都不会正确转换此文档.
这是一个操作DOM树以产生最终结果的实现:
var stringXML = '<abc xmlns="http://mydefaulns.com" xmlns:my="http://mydefaulns.com" xmlns:other="http://other.com">\n\ <node1>Value</node1>\n\ <other:node2>Value2</other:node2>\n\ </abc>'; var defaultNS = "http://mydefaulns.com"; var xmlDoc = $.parseXML(stringXML); xmlDoc.firstChild.removeAttribute("xmlns"); // Make sure we do have xmlns:my defined. xmlDoc.firstChild.setAttribute("xmlns:my",defaultNS); function transformChildren(parent) { // We take a copy of childNodes before clearing it. var childNodes = Array.prototype.slice.call(parent.childNodes); while (parent.firstChild) { parent.removeChild(parent.firstChild); } var newChild; var limit = childNodes.length; for (var childIx = 0; childIx < limit; ++childIx) { newChild = undefined; var node = childNodes[childIx]; if (node.nodeType === Node.ELEMENT_NODE && node.namespaceURI === defaultNS) { newChild = xmlDoc.createElementNS(defaultNS,"my:" + node.tagName); // Copy the attributes. var attributes = node.attributes; for (var attrIx = 0; attrIx < attributes.length; ++attrIx) { var attr = attributes[attrIx]; newChild.setAttributeNS(attr.namespaceURI,attr.name,attr.value) } // Move the children. while (node.firstChild) { newChild.appendChild(node.firstChild); } transformChildren(newChild); } parent.appendChild(newChild || node); } } transformChildren(xmlDoc); // This is just reused from the question. function XMLDocumentToString(oXML) { if (typeof oXML.xml != "undefined") { return oXML.xml; } else if (XMLSerializer) { return (new XMLSerializer().serializeToString(oXML)); } else { throw "Unable to serialize the XML"; } } console.log(XMLDocumentToString(xmlDoc));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>