是否可以使用 Saxon-JS 将 JSON 文件转换为不同的 JSON 文件而不通过 XML 传输?

Is it possible to use Saxon-JS to convert a JSON file to a different JSON file without transiting through XML?

我正在研究解决从根本上完全基于 JSON 的转换问题,虽然基于命令式代码的解决方案是可能的,但使用像 XSLT 这样的成熟技术并利用其许多功能,而不是尝试从头开始内部所有的东西。我对 XSLT 相当缺乏经验,但我很乐意为此努力提供一个学习它的理由。

我读到 JSON 包含在 XSLT 3.0 和 XPath 3.1 规范中,并且 Saxon-JS 支持这些,而且 Saxon-JS 有一个 node.js 版本。这让我很感兴趣,但我没有找到太多关于如何将 JSON 转换为其他 JSON 的教程;相反,重点似乎是将 JSON 转换为 XML.

这个问题有点宽泛,所以我很乐意知道这是否可行,以及从哪里开始学习,但 Whosebug 喜欢示例。考虑到这一点,将这些 JSON 文档中的第一个转换为第二个的样式表会是什么样子?

来源:

{
    "contents" : [
        {
            "id": 1,
            "color": "blue",
            "hexcode": "#0000FF"
        },
        {
            "id": 2,
            "color": "green",
            "hexcode": "#00FF00"
        },
        {
            "id": 3,
            "color": "red",
            "hexcode": "#FF0000"
        }
    ]
}

输出:

[
    {
        "id": "contents1",
        "color": {
            "name": "blue",
            "hexcode": "#0000FF"
        }
    },
    {
        "id": "contents2",
        "color": {
            "name": "green",
            "hexcode": "#00FF00"
        }
    },
    {
        "id": "contents3",
        "color": {
            "name": "red",
            "hexcode": "#FF0000"
        }
    }
]

如果你使用

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="3.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="#all">
  
  <xsl:output method="json" indent="yes"/>
  
  <xsl:template match=".[. instance of map(*)]">
    <xsl:sequence
      select="array{ ?contents?*!map { 'id' : 'contents' || ?id, 'color' : map { 'name' : ?color, 'hexcode' : ?hexcode } } }"/>
  </xsl:template>
  
</xsl:stylesheet>

例如at the Saxon-JS fiddle 然后 JSON 被解析为 XPath 3.1 映射并构造一个 XPath 3.1 数组,该数组被序列化回 JSON.

对于 Node.js xslt3 命令行工具,您可以使用 -json:my-input.json 我认为您可以使用 s:my-source.xml 来转换 XML。我认为 -json 选项仅在 Saxon-JS 2.3 中,因此请确保使用最新版本。

对于仅使用 JSON 的 maps/arrays 的 XDM 表示而不是使用 XML 表示的更一般的处理和优缺点的辩论json-to-xml 参见 https://www.saxonica.com/papers/xmlprague-2016mhk.pdf, https://dev.saxonica.com/blog/mike/2017/11/transforming-json.html, https://www.youtube.com/watch?v=hGehtNUrg60

有关查询 XPath 3.1 映射和数组的语法,请参阅 https://www.altova.com/training/xpath3/xpath-31 或 XPath 3.1 规范或有关 XPath 3.1 的任何其他教程 arrays/maps。

是的,正如马丁所展示的那样,这是可能的。然而,在 JSON-to-JSON 转换工作像 XML-to-XML 一样顺利之前,XSLT 还有一点路要走。我经验的主要限制是:

(a) 为 xsl:template 编写匹配 JSON 树

中的“节点”的匹配模式并不容易

(b) 因为 JSON 没有父轴或祖先轴,JSON 树中特定“节点”的处理无法访问它出现的上下文,这意味着有必要使用模板参数向下传递该上下文(隧道参数对此非常有用。)

在您的示例中,输入数据是完全平坦的,因此不会出现这些问题。