Javascript 当属性具有xlink命名空间时,Chrome 22输出无效的XML

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

我有以下最小的JavaScript片段:

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处理的报告。但我实际上担心,这方面的“修复”可能是导致我所经历的问题的原因。有了你的链接,我可能会更接近那些令人讨厌的代码,所以谢谢!