Javascript 当属性具有xlink命名空间时,Chrome 22输出无效的XML
我有以下最小的JavaScript片段:Javascript 当属性具有xlink命名空间时,Chrome 22输出无效的XML,javascript,google-chrome,xmlserializer,Javascript,Google Chrome,Xmlserializer,我有以下最小的JavaScript片段: var xml=''; var dom=new DOMParser().parseFromString(xml,'text/xml'); xml=新的XMLSerializer().serializeToString(dom); 当我在大多数浏览器中执行代码时(只需将其粘贴到浏览器的JavaScript控制台中),经过解析然后序列化的XML与原始XML是等效的。例如,在Chrome 8上,我得到: 但是,在Chrome 22上,相同的代码片段将XM
var xml='';
var dom=new DOMParser().parseFromString(xml,'text/xml');
xml=新的XMLSerializer().serializeToString(dom);
当我在大多数浏览器中执行代码时(只需将其粘贴到浏览器的JavaScript控制台中),经过解析然后序列化的XML与原始XML是等效的。例如,在Chrome 8上,我得到:
但是,在Chrome 22上,相同的代码片段将XML更改为:
请注意,title和href属性使用的名称空间前缀xlink
没有在任何地方定义,因此XML现在无效。正如您可能想象的那样,这会导致尝试随后使用XML的代码出现各种各样的问题
这是XMLSerializer中的一个bug,还是我遗漏了一些关于DOM应该如何序列化的复杂问题
还有没有人找到一种我可以在代码中使用的解决方法,而不是让XML与使用xlink
作为xlink名称空间前缀的明显偏好相匹配
更新
我做了一些额外的测试,问题似乎是由XMLSerializer识别XLink名称空间并坚持为其输出XLink
前缀而没有正确注册该前缀这一事实引起的
所以这个片段很好:
var xml='';
var dom=new DOMParser().parseFromString(xml,'text/xml');
xml=新的XMLSerializer().serializeToString(dom);
因此,我在这里将名称空间URL更改为不太为人所知的内容,并且输出现在是有效的:
以下片段也可以正常工作:
var xml='';
var dom=new DOMParser().parseFromString(xml,'text/xml');
xml=新的XMLSerializer().serializeToString(dom);
因此,在本例中,我们为XLink名称空间使用“预期”前缀,然后它将毫无问题地序列化:
我仍然非常确定Chrome的
XMLSerializer
中存在一个bug,很可能是在解决问题时引入的。但鉴于对我提出的问题缺乏回应,我们不得不向前迈进,努力解决这个问题
我们通过在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]);
}
}
}
函数EnsureXlinkNamespaceOneElement(元素)
{
if(element.nodeType==1)
{
var usesXLinkNamespaceUri=false;
var hasXLinkNamespacePrefixDefined=false;
对于(var i=0;i
该函数只是确保在xlink命名空间中具有属性的任何元素上声明xmlns:xlink
属性。由于该函数遍历树,因此可能非常耗时,因此我只在Chrome版本22及更高版本中调用它
请注意,在大多数情况下,只需在document元素上添加xmlns:xlink
名称空间也可以解决问题,因为它将从那里继承。但在我们的例子中,还有一些代码使用正则表达式剥离文档元素,因此我们决定安全起见,只需在需要的地方添加属性
更新(20130324):
在Chrome Canary 26中固定并验证了该系统。我已经能够在版本
25.0.1364.172 m
上自己验证它。我不完全确定答案是什么,但这个问题可能与此相关:感谢Barbarrosa提供的指针。我看过关于Chrome的SVG/XLink处理的报告。但我实际上担心,这方面的“修复”可能是导致我所经历的问题的原因。有了你的链接,我可能会更接近那些令人讨厌的代码,所以谢谢!