如何在javascript中为默认命名空间中的XML节点分配前缀?

Mel*_*nie 10 javascript xml

我有一个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";
    }
}
Run Code Online (Sandbox Code Playgroud)

但它没有影响,当我写回来时,仍然没有前缀.

我还尝试加载XML并调用:

xmlDoc.firstChild.removeAttribute("xmlns")
Run Code Online (Sandbox Code Playgroud)

但该属性未被删除,因此前缀不会神奇地更新.

那时,我认为获得我想要的结果的唯一方法是使用新的前缀名称重新创建所有节点,复制所有属性.

这看起来非常极端,还有另一种方式吗?

输入(字符串):

<abc xmlns="http://mydefaulns.com" xmlns:my="http://mydefaulns.com"xmlns:other="http://other.com">
    <node1>Value</node1>
    <other:node2>Value2</other:node2>
</abc>
Run Code Online (Sandbox Code Playgroud)

期望的输出:

<my:abc xmlns:my="http://mydefaulns.com"xmlns:other="http://other.com">
    <my:node1>Value</my:node1>
    <other:node2>Value2</other:node2>
</my:abc>
Run Code Online (Sandbox Code Playgroud)

实际的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";
    }    
 }
Run Code Online (Sandbox Code Playgroud)

ibr*_*rir 5

无需解析XML字符串只需使用replace带有regular expressions这样的:

var prefix = "my:";
stringXML = stringXML.replace(/(<\/?)(\w+)(?!:)(\b)/g, "$1" + prefix + "$2$3");
Run Code Online (Sandbox Code Playgroud)

这将匹配任何字母序列(有效的标签名称)恰好在a <</(<必要的,/是可选的)之后,而不是a :后面跟着\b.

var stringXML = '<abc xmlns="http://mydefaulns.com" xmlns:my="http://mydefaulns.com" xmlns:other="http://other.com"><node1>Value</node1><other:node2>Value2</other:node2></abc>';

console.log("BEFORE: ", stringXML);

var prefix = "my:";
stringXML = stringXML.replace(/(<\/?)(\w+)(?!:)(\b)/g, "$1" + prefix + "$2$3");

console.log("AFTER: ", stringXML);
Run Code Online (Sandbox Code Playgroud)


Lou*_*uis 4

那时,我认为获得我想要的结果的唯一方法是使用新的前缀名称重新创建所有节点,复制所有属性。

是的,如果你想做得干净利落,这正是你必须做的。

使用正则表达式的解决方案很脆弱。这是您给出的示例:

<abc xmlns="http://mydefaulns.com" xmlns:my="http://mydefaulns.com" xmlns:other="http://other.com">
    <node1>Value</node1>
    <other:node2>Value2</other:node2>
</abc>
Run Code Online (Sandbox Code Playgroud)

现在考虑以下文档,它相当于您的原始文档:

<abc xmlns="http://mydefaulns.com" xmlns:my="http://mydefaulns.com">
    <node1>Value</node1>
    <node2 xmlns="http://other.com">Value2</node2>
</abc>
Run Code Online (Sandbox Code Playgroud)

唯一改变的是node2命名空间中的元素如何http://other.com分配命名空间。在您的原始文档中,它是通过other在根节点上定义的前缀实现的。这里是通过重新定义node2. 从 XML 的角度来看,这两个文档是相同的node2如何定义 的命名空间并不重要。但问题是,您获得的两个基于正则表达式的答案都无法正确转换此文档。

下面是一个操作 DOM 树以产生最终结果的实现:

<abc xmlns="http://mydefaulns.com" xmlns:my="http://mydefaulns.com" xmlns:other="http://other.com">
    <node1>Value</node1>
    <other:node2>Value2</other:node2>
</abc>
Run Code Online (Sandbox Code Playgroud)
<abc xmlns="http://mydefaulns.com" xmlns:my="http://mydefaulns.com">
    <node1>Value</node1>
    <node2 xmlns="http://other.com">Value2</node2>
</abc>
Run Code Online (Sandbox Code Playgroud)