使用XSLT将XML转换为JSON

时间:2019-09-25 18:26:09

标签: json xml xslt xslt-3.0

我想使用XSLT将一些XML转换为JSON。
XML如下所示:

<DATA_DS>
    <G_1>
        <ORGANIZATION_NAME>My Company 1</ORGANIZATION_NAME>
        <ORGANIZATIONID>901</ORGANIZATIONID>
        <ITEMNUMBER>20001</ITEMNUMBER>
        <ITEMDESCRIPTION>Item Description 1</ITEMDESCRIPTION>
    </G_1>
    <G_1>
        <ORGANIZATION_NAME>My Company 1</ORGANIZATION_NAME>
        <ORGANIZATIONID>901</ORGANIZATIONID>
        <ITEMNUMBER>20002</ITEMNUMBER>
        <ITEMDESCRIPTION>Item Description 2</ITEMDESCRIPTION>
    </G_1>
    <G_1>
        <ORGANIZATION_NAME>My Company 1</ORGANIZATION_NAME>
        <ORGANIZATIONID>901</ORGANIZATIONID>
        <ITEMNUMBER>20003</ITEMNUMBER>
        <ITEMDESCRIPTION>Item Description 3</ITEMDESCRIPTION>
    </G_1>
</DATA_DS>

我希望JSON如下所示:

    [
        {
            "Item_Number":"20001",
            "Item_Description":"Item Description 1"
        },
        {
            "Item_Number":"20002",
            "Item_Description":"Item Description 2"
        },
        {
            "Item_Number":"20003",
            "Item_Description":"Item Description 3"
        }
    ]

推荐的方法是什么?

我正在考虑两种方法:

  1. 尝试使用https://www.w3.org/TR/xpath-functions-31/#func-xml-to-json中定义的fn:xml-to-json函数。但是据我了解,输入XML必须遵循在https://www.w3.org/TR/xpath-functions-31/schema-for-json.xsd处定义的特定格式。而且我还需要输出JSON中的字段名称特别是“ Item_Number”和“ Item_Description”。

  2. 手动编码方括号和大括号字符“ [],“]”,“ {”和“}”,以及字段名称“ Item_Number”和“ Item_Description”。然后使用标准函数列出值,并确保正确处理任何特殊字符。例如,“&”字符应正常显示在JSON输出中。

推荐这样做的方法是什么,还是有我没有考虑过的更好的方法?

3 个答案:

答案 0 :(得分:2)

我将采用第一种方法,但首先将给定的输入转换为xml-to-json()函数期望的XML格式。可能是这样的:

XSLT 3.0

<xsl:stylesheet version="3.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/2005/xpath-functions">
<xsl:output method="text" encoding="UTF-8"/>

<xsl:template match="/G_1">
    <!-- CONVERT INPUT TO XML FOR JSON -->
    <xsl:variable name="xml">
        <array>
            <xsl:for-each-group select="*" group-starting-with="ORGANIZATION_NAME">
                <map>
                    <string key="Item_Number">
                        <xsl:value-of select="current-group()[self::ITEMNUMBER]"/>
                    </string>
                    <string key="Item_Description">
                        <xsl:value-of select="current-group()[self::ITEMDESCRIPTION]"/>
                    </string>
                </map>
            </xsl:for-each-group>
        </array>
    </xsl:variable>
    <!-- OUTPUT -->
    <xsl:value-of select="xml-to-json($xml)"/>
</xsl:template>

</xsl:stylesheet>

演示: https://xsltfiddle.liberty-development.net/bFWR5DQ

答案 1 :(得分:0)

这是采用michael.hor257k发布的解决方案并将其应用于我的修订输入XML的结果:

<xsl:stylesheet version="3.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns="http://www.w3.org/2005/xpath-functions">
    <xsl:output method="text" encoding="UTF-8"/>

    <xsl:template match="/DATA_DS">
        <!-- CONVERT INPUT TO XML FOR JSON -->
        <xsl:variable name="xml">
            <array>
                <xsl:for-each  select="G_1">
                <map>
                    <string key="Item_Number">
                        <xsl:value-of select="ITEMNUMBER"/>
                    </string>
                    <string key="Item_Description">
                        <xsl:value-of select="ITEMDESCRIPTION"/>
                    </string>
                </map>
            </xsl:for-each>
            </array>
        </xsl:variable>
        <!-- OUTPUT -->
         <xsl:value-of select="xml-to-json($xml)"/>
    </xsl:template>

</xsl:stylesheet>

答案 2 :(得分:0)

对于像这样的简单映射,您还可以直接构造XPath 3.1数组和映射,即在这种情况下为映射数组:

  <xsl:template match="DATA_DS">
      <xsl:sequence select="array { G_1 ! map { 'Item_Number' : string(ITEMNUMBER), 'Item_Description' : string(ITEMDESCRIPTION) } }"/>
  </xsl:template>

然后使用<xsl:output method="json" indent="yes"/>https://xsltfiddle.liberty-development.net/ejivdGS

序列化为JSON

主要缺点是地图没有顺序,因此您无法控制地图中项目的顺序,例如,在该示例中,使用的Saxon版本Item_DescriptionItem_Number之前输出

但是通常,转换为xml-to-json的格式可以提供更大的灵活性,并且由于该函数将顺序保留在JSON的XML表示中,因此还可以控制顺序。