Fra*_*len 23 javascript google-chrome xmlserializer
我有以下最小的JavaScript片段:
var xml = '<El a:title="T" a:href="H" xmlns:a="http://www.w3.org/1999/xlink" />';
var dom = new DOMParser().parseFromString(xml, 'text/xml');
xml = new XMLSerializer().serializeToString(dom);
Run Code Online (Sandbox Code Playgroud)
当我在大多数浏览器中执行代码时(只需将其粘贴到浏览器的JavaScript控制台中),解析后序列化的XML与原始XML相同.例如在Chrome 8上,我得到:
<El xmlns:a="http://www.w3.org/1999/xlink" a:title="T" a:href="H"/>
Run Code Online (Sandbox Code Playgroud)
但是在Chrome 22上,相同的代码片段将XML更改为:
<El xmlns:a="http://www.w3.org/1999/xlink" xlink:title="T" xlink:href="H"/>
Run Code Online (Sandbox Code Playgroud)
请注意,xlink
title和href属性使用的名称空间前缀未在任何位置定义,因此XML现在无效.正如您可能想象的那样,这会导致尝试随后使用XML的代码出现各种问题.
这是XMLSerializer中的错误还是我错过了关于如何序列化DOM的一些错综复杂的内容?
还有没有人找到我可以放在代码中的解决方法,而不是使XML匹配明显的首选项xlink
用作XLink命名空间的前缀?
我做了一些额外的测试,问题似乎是因为XMLSerializer识别XLink命名空间并坚持xlink
为它输出前缀,而没有正确注册该前缀.
所以这个片段工作正常:
var xml = '<El a:title="T" a:href="H" xmlns:a="any-other-namespace-uri" />';
var dom = new DOMParser().parseFromString(xml, 'text/xml');
xml = new XMLSerializer().serializeToString(dom);
Run Code Online (Sandbox Code Playgroud)
所以在这里我将名称空间URL更改为不太知名的东西,输出现在有效:
<El xmlns:a="any-other-namespace-uri" a:title="T" a:href="H"/>
Run Code Online (Sandbox Code Playgroud)
以下片段也可以正常工作:
var xml = '<El a:title="T" a:href="H" xmlns:a="http://www.w3.org/2000/xlink" />';
var dom = new DOMParser().parseFromString(xml, 'text/xml');
xml = new XMLSerializer().serializeToString(dom);
Run Code Online (Sandbox Code Playgroud)
因此,在这种情况下,我们使用XLink命名空间的"预期"前缀,然后序列化没有问题:
<El xmlns:a="http://www.w3.org/2000/xlink" a:title="T" a:href="H"/>
Run Code Online (Sandbox Code Playgroud)
我仍然非常肯定Chrome中存在一个错误XMLSerializer
,很可能是在解决Barbarrosa指出的XLink属性的SVG处理时引入的.但鉴于我对它所做的错误报告缺乏回应,我们不得不前进并解决问题.
我们通过在以下方面调用此函数来解决此问题documentElement
:
function EnsureXLinkNamespaceOnElement(element)
{
if (element.nodeType == 1)
{
var usesXLinkNamespaceUri = false;
var hasXLinkNamespacePrefixDefined = false;
for (var i = 0; i < element.attributes.length; i++)
{
var attribute = element.attributes[i];
if (attribute.specified)
{
if (attribute.name.indexOf("xmlns:xlink") == 0)
{
hasXLinkNamespacePrefixDefined = true;
}
else if (attribute.namespaceURI == "http://www.w3.org/1999/xlink")
{
usesXLinkNamespaceUri = true;
}
}
}
if (usesXLinkNamespaceUri && !hasXLinkNamespacePrefixDefined)
{
element.setAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink');
}
for (i = 0; i < element.childNodes.length; i++)
{
EnsureXLinkNamespaceOnElement(element.childNodes[i]);
}
}
}
Run Code Online (Sandbox Code Playgroud)
该函数只是确保xmlns:xlink
在XLink命名空间中归属的任何元素上声明属性.由于该函数遍历树,因此可能非常耗时,因此我仅针对Chrome版本22及更高版本调用它.
请注意,在大多数情况下,您只需xmlns:xlink
在文档元素上添加命名空间即可,因为它将从那里继承.但在我们的例子中,有一些其他代码使用正则表达式去除文档元素,因此我们决定安全地使用它,只需在可能需要的任何地方添加属性.
该错误已在Chrome Canary 26中修复和验证.我已经能够在版本上验证它25.0.1364.172 m
.
归档时间: |
|
查看次数: |
1898 次 |
最近记录: |