Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/457.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript xml到json映射挑战_Javascript_Xml_Json_Mapping_Format Conversion - Fatal编程技术网

Javascript xml到json映射挑战

Javascript xml到json映射挑战,javascript,xml,json,mapping,format-conversion,Javascript,Xml,Json,Mapping,Format Conversion,乍一看,我认为在javascript中使用xml数据就像查找xml到json库并将xml转换为javascript对象树一样简单 然而,现在我意识到可以用xml创建不直接映射到json的结构 具体而言,这: <parentNode> <fooNode>data1</fooNode> <barNode>data2</barNode> <fooNode>data3</fooNode> <

乍一看,我认为在javascript中使用xml数据就像查找xml到json库并将xml转换为javascript对象树一样简单

然而,现在我意识到可以用xml创建不直接映射到json的结构

具体而言,这:

<parentNode>
    <fooNode>data1</fooNode>
    <barNode>data2</barNode>
    <fooNode>data3</fooNode>
</parentNode>
}

其中,子节点的顺序已更改。我需要保留子节点的顺序。任何人都有比这更优雅的解决方案

a) 放弃自动转换的想法,只需设计自己的javascript对象结构并编写代码来处理这个特定的xml模式


b) 完全放弃任何转换的想法,将我的xml数据作为xml文档,然后我将遍历它。

如果您经常需要相同的元素名称,并且关心排序,那么最好还是使用xml。使用JSON有什么好处?

为什么不试试:

{ parentNode: [
  ["fooNode", "data1"],
  ["barNode", "data2"],
  ["fooNode", "data3"] ]
}
我认为这或多或少会解决这个问题


是的,我认为如果自动转换不够灵活,你应该放弃它;相反,您可能会寻找一个使此类映射变得微不足道的API。

有一些已建立的从XML到JSON的映射,但有一些限制(请参阅),还有从JSON到XML的映射(请参阅JSONx as和)。然而,还没有定义从XML到JSON的映射来保持顺序。要完全捕获XML的所有方面,应该用JSON表示XML。如果您只关心XML元素(没有处理指令等),我会选择以下结构:

[
  "parentNode",
  { } /* attributes */
  [ 
    [ "fooNode", { }, [ "data1" ] ]
    [ "fooNode", { }, [ "data2" ] ]
    [ "fooNode", { }, [ "data3" ] ]
  ]
]

我实现了与XML和Perl数据结构之间的映射相同的映射,这些数据结构与JSON相同。该结构进一步对应于XML的一个简化子集的抽象数据模型。

我最近设计了这个:

(只是一个思维实验)

(at)

快速理由:

XML元素是唯一接受混合内容(文本节点和/或其他元素、注释、PI)的节点类型(除了文档根),并定义其子节点的顺序;因此使用JSON数组(子索引基于1,而不是基于0,因为保留索引0携带节点类型(元素)信息;但可以注意到XPath节点集也使用基于1的索引(顺便说一句)

XML属性名/值映射不需要对键(属性名)wrt.owner元素进行任何排序,只需要该元素节点上键的唯一性;因此在容器数组的索引0处使用JSON对象(对应于owner元素)

最后,毕竟,虽然“”是对象值中完全有效的JSON键,但XML元素或属性也不能有空名称……因此使用“”作为特殊的常规键来提供元素名称

下面是使用我的小“JSLT”(at)将其转换为HTML的步骤:

收益率(作为字符串):


文件标题
标题1

段落(第1行)
续(第2行)

(但是上面的转换也可以很容易地调整为使用DOM节点工厂,并构建实际的DOM文档,而不是构建字符串)


“HTH,

当您将XML转换为JSON时,为什么顺序很重要?难道“节点顺序”不是XML特有的问题吗?您可以更改dom节点的行为以使您的生活更轻松。或者您可以将其包装。这也是我可能会做的,但我可能更喜欢:
{parentNode:[{key:val},…}
而不是2元素数组。我不得不偶然发现这个问题和你的好答案来阅读MicroXML。有趣的是,我们经常需要独立地解决相同的问题和/或类似的解决方案。对如何将XML转换为JSON(反之亦然)感兴趣往返,我最终想到了这样的东西:
[
  "parentNode",
  { } /* attributes */
  [ 
    [ "fooNode", { }, [ "data1" ] ]
    [ "fooNode", { }, [ "data2" ] ]
    [ "fooNode", { }, [ "data3" ] ]
  ]
]
var someTinyInfosetSample = {
  "doctype": "html",
  "$": [
    { "": "html" },
    [ { "": "head" },
       [ { "": "title" }, "Document title" ]
    ],
    [ { "": "body" },
      [ { "": "h1" }, "Header 1" ],
      [ { "": "p", "class": "content" },
        "Paragraph... (line 1)", [ { "": "br" } ],
        "... continued (line 2)"
      ]
    ]
  ] };
var tinyInfosetJSLT = { $: [
  [ [ function/*Root*/(node) { return node.$; } ],
      function(root) { return Per(this).map(root.$); }
  ],
  [ [ function/*Element*/(node) { return { }.toString.call(node) === "[object Array]"; } ],
      function(element) {
        var children = (element.length > 1 ? element.slice(1) : null),
            startTag = element[0],
            nodeName = startTag[""],
            self = this;
        return children ?
               Per("\r\n<{stag}>{content}</{etag}>\r\n").map
               ({
                 stag: Per(this).map(startTag),
                 etag: nodeName,
                 content: Per(children).map(function(child) { return Per(self).map(child); }).join("")
               })
               :
               Per("<{stag}/>").map({ stag: Per(this).map(startTag) });
      }
  ],
  [ [ function/*StartTag*/(node) { return node[""]; } ],
      function(startTag) {
        var tag = [ startTag[""] ];
        for (var attribute in startTag) {
          if (attribute !== "") {
            tag.push
            (
              Per("{name}=\"{value}\"").
              map({ name: attribute, value: startTag[attribute].replace('"', "&quot;") })
            );
          }
        }
        return tag.join(" ");
      }
  ],
  [ [ function/*Text*/(node) { return typeof node === "string"; } ],
      function(text) {
        return text.
               replace("\t", "&x09;").
               replace("\n", "&x0A;").
               replace("\r", "&x0D;");
      }
  ]
] };
Per(tinyInfosetJSLT).map(someTinyInfosetSample)
<html>
<head>
<title>Document title</title>
</head>

<body>
<h1>Header 1</h1>

<p class="content">Paragraph... (line 1)<br/>... continued (line 2)</p>
</body>
</html>