【问题标题】:Subtle difference in XMLSerializer in Firefox vs Chrome?Firefox 和 Chrome 中 XMLSerializer 的细微差别?
【发布时间】:2013-01-09 23:46:33
【问题描述】:

以下 sn-p 代码使用 createDocument 和 XMLSerializer API 将 Javascript 对象转换为 XML 字符串。问题是它在 Chrome (23.0.1271.101) 和 Firefox (14.0.1) 浏览器上生成不同的输出。

var item = { _dto: {...} }; // the 'model' object
var xmlDto = $('<Column />'); // this is eventually serialized and sent to the server
var optionalTags = ['Abstract', 'Note', 'Size', 'Digits', 'Nullable', 'AutoUpdate', 'DataType'];

// convert badgerfish JSON back to XML.
// use XML because it is not possible serialize JSON and preserve key order.
var xmlDoc = document.implementation.createDocument("http://example.org/v1", "Column", null);
var root = xmlDoc.childNodes[0];
var nameTag = xmlDoc.createElement("Name");
nameTag.setAttribute('uuid', item._dto['Name']['@uuid']);
nameTag.textContent=item._dto['Name']['$'];
root.appendChild(nameTag);
optionalTags.map(function (tagName) {
    var tag = xmlDoc.createElement(tagName);
    tag.textContent=item._dto[tagName];
    if (item._dto.hasOwnProperty(tagName)) {
        tag.textContent=item._dto[tagName];
        root.appendChild(tag);
    }
});

var xmlStr = new XMLSerializer().serializeToString(xmlDoc);
xmlStr = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'+xmlStr;

在 Chrome 上,会生成以下所需/预期的输出:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <Column xmlns="http://example.org/v1">
          <Name uuid="001b5cbe-bab7-4880-90b6-9e8f47f6e4af">FAILED_ID</Name>
          <Size>38</Size>
          <Digits>0</Digits>
          <Nullable>true</Nullable>
          <AutoUpdate>false</AutoUpdate>
          <DataType>NUMERIC</DataType>
    </Column>

但在 Firefox 中,生成的输出在每个标签中插入了 xmlns 属性,其值为空:

     <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
     <Column xmlns="http://example.org/v1">
          <Name xmlns="" uuid="001b5cbe-bab7-4880-90b6-9e8f47f6e4af">FAILED_ID</Name>
          <Size xmlns="">38</Size>
          <Digits xmlns="">0</Digits>
          <Nullable xmlns="">true</Nullable>
          <AutoUpdate xmlns="">false</AutoUpdate>
          <DataType xmlns="">NUMERIC</DataType>
     </Column>

看起来 Firefox 和 Chrome 中的 XMLSerializer 有细微的差异,但我需要验证这一点。在任何情况下,Firefox 输出都是无效的 XML。有人可以解释一下吗?

有没有更好的方法在浏览器中生成 XML 文档?

如果一开始我有办法序列化为 JSON 并能够保留键顺序,我就不会这样做。

【问题讨论】:

  • 我们无法控制 XMLSerializer 的默认/假设,firefox 生成的不是无效文档,而是命名空间处理的实现细节。您可以从 'xmlDoc.createElement("Name");' 切换到 'xmlDoc.createElementNS("example.org/v1","Name"); ' 这应该可以帮助您解决问题
  • 正如其他人所说,尝试将 var tag = xmlDoc.createElement(tagName); 更改为 var tag = xmlDoc.createElementNS('http://example.org/v1', tagName); 以在所需的命名空间中包含元素。

标签: xml json google-chrome firefox xmlserializer


【解决方案1】:

Firefox 序列化是正确的。当您使用createElement(而不是createElementNS)创建这些元素时,会将它们置于空命名空间中(您可以在创建它们后通过检查元素的namespaceURI 进行检查)。然而,解析 Chrome 产生的序列化会将它们放在 http://example.org/v1 命名空间中。

是的,Firefox 输出是有效的 XML。是什么让您认为它无效?

我提交了https://bugs.webkit.org/show_bug.cgi?id=106531

【讨论】:

  • IMO 我不认为这是 Chrome 中的错误,而是 FF 的问题。如果遵循 XSD 规则,一般约定是默认情况下所有元素都是不合格的命名空间,并且只有在需要覆盖父元素命名空间时才会使用 createElementNS。在每个实例中都使用 createElementNS 会非常不方便。
  • 创建元素时没有父元素。所以它只是在 null 命名空间中创建的。请注意,有人建议改用 XHTML 命名空间,在这种情况下,您的元素最终会出现在 XHTML 命名空间中,这可能对您的目的同样不利。我同意这很不方便,但元素的命名空间是不可变的,因此必须在创建时设置。在任何情况下,两个浏览器都会在您创建元素时将它们放在 null 命名空间中。 Chrome 只是搞砸了序列化。
  • 我的服务器是 Apache CXF,它拒绝由 Firefox 生成的文档,如示例中所述,仅使用 createElement。使用 createElementNS 在 Chrome 和 Firefox 上生成相同的输出,我的服务器能够正确处理。
  • 好吧,Firefox 生成的文档可能与您的架构不匹配,这就是它被拒绝的原因。但它是格式良好的 XML,并且 确实 匹配被序列化的 DOM。 Chrome 文档是格式良好的 XML,但与被序列化的 DOM 不匹配,因此最终会出现“两个错误相互抵消”的情况。 ;)
猜你喜欢
  • 2016-11-22
  • 1970-01-01
  • 2011-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-28
  • 2011-07-08
  • 2011-04-26
相关资源
最近更新 更多