使用 xslt 将 xml 转换为 json

问题描述:

尝试使用通用 xslt 将 xml 转换为 json

Trying to convert xml to json using generic xslt

输入xml:

<Response>
<Info>
    <Domain/>
    <Source/>
</Info>
<OrderDetails itemNo="1 ">
    <OrderNum>0002060412</OrderNum>
    <sourceType>UTD</sourceType>
    <organization>UTD09</organization>
    <AmtAdjust>Not Known-Need Coding</AmtAdjust>
</OrderDetails>
<OrderDetails itemNo="2 ">
    <OrderNum>0002060415</OrderNum>
    <sourceType>UTD</sourceType>
    <organization>UTD09</organization>
    <AmtAdjust>Not Known-Need Coding</AmtAdjust>
</OrderDetails>
<OrderDetails itemNo="3 ">
    <OrderNum>0002060413</OrderNum>
    <sourceType>UTD</sourceType>
    <organization>UTD09</organization>
    <AmtAdjust>Not Known-Need Coding</AmtAdjust>
</OrderDetails>
<OrderDetails itemNo="5 ">
    <OrderNum>0060064425</OrderNum>
    <sourceType>UTD</sourceType>
    <organization>UTD09</organization>
    <TickNums>
        <TktNum>11776564428635</TktNum>
    </TickNums>
    <LineDetail>
        <itemNum>000010</itemNum>
        <type>ftr</type>
        <amnt>100.000000000 </amnt>
        <qty>1.000 </qty>
        <center>0002/0002</center>
    </LineDetail>
    <LineDetail>
        <itemNum>000020</itemNum>
        <type>ert</type>
        <amnt>30.000000000 </amnt>
        <qty>1.000 </qty>
        <center>0002/0002</center>
    </LineDetail>
    <LineDetail>
        <itemNum>000030</itemNum>
        <type>VAT</type>
        <amnt>10.000000000 </amnt>
        <qty>1.000 </qty>
        <center>0002/0002</center>
    </LineDetail>
    <LineDetail>
        <itemNum>000040</itemNum>
        <type>C2</type>
        <amnt>20.000000000 </amnt>
        <qty>1.000 </qty>
        <center>0002/0002</center>
    </LineDetail>
    <AmtAdjust>Not Known-Need Coding</AmtAdjust>
</OrderDetails>
<OrderDetails itemNo="6 ">
    <OrderNum>0060064427</OrderNum>
    <sourceType>UTD</sourceType>
    <organization>UTD09</organization>
    <TickNums>
        <TktNum>11234569354874</TktNum>
    </TickNums>
    <TickNums>
        <TktNum>45465749854377</TktNum>
    </TickNums>
    <LineDetail>
        <itemNum>000010</itemNum>
        <type>BR</type>
        <amnt>100.000000000 </amnt>
        <qty>1.000 </qty>
        <center>0002/0002</center>
    </LineDetail>
    <LineDetail>
        <itemNum>000020</itemNum>
        <type>ytr</type>
        <amnt>100.000000000 </amnt>
        <qty>1.000 </qty>
        <center>0002/0002</center>
    </LineDetail>
    <LineDetail>
        <itemNum>000030</itemNum>
        <type>COMM</type>
        <amnt>200.000000000 </amnt>
        <qty>1.000 </qty>
        <center>0002/0002</center>
    </LineDetail>
    <AmtAdjust>Not Known-Need Coding</AmtAdjust>
</OrderDetails>

我常用的xslt:

  <?xml version="1.0"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>

    <xsl:template match="/">{
        <xsl:apply-templates select="*"/>}
    </xsl:template>

    <!-- Object or Element Property-->
    <xsl:template match="*">
        "<xsl:value-of select="name()"/>" :<xsl:call-template name="Properties">
            <xsl:with-param name="parent" select="'Yes'"> </xsl:with-param>
        </xsl:call-template>
    </xsl:template>

    <!-- Array Element -->
    <xsl:template match="*" mode="ArrayElement">
        <xsl:call-template name="Properties"/>
    </xsl:template>

    <!-- Object Properties -->
    <xsl:template name="Properties">
        <xsl:param name="parent"></xsl:param>
        <xsl:variable name="childName" select="name(*[1])"/>
        <xsl:choose>            
            <xsl:when test="not(*|@*)"><xsl:choose><xsl:when test="$parent='Yes'"> <xsl:text>&quot;</xsl:text><xsl:value-of select="."/><xsl:text>&quot;</xsl:text></xsl:when>
                    <xsl:otherwise>"<xsl:value-of select="name()"/>":"<xsl:value-of  select="."/>"</xsl:otherwise>
                </xsl:choose>           
            </xsl:when>                
            <xsl:when test="count(*[name()=$childName]) > 1">{ "<xsl:value-of  select="$childName"/>" :[<xsl:apply-templates select="*" mode="ArrayElement"/>] }</xsl:when>
            <xsl:otherwise>{
                <xsl:apply-templates select="@*"/>
                <xsl:apply-templates select="*"/>
                }</xsl:otherwise>
        </xsl:choose>
        <xsl:if test="following-sibling::*">,</xsl:if>
    </xsl:template>

    <!-- Attribute Property -->
    <xsl:template match="@*">"<xsl:value-of select="name()"/>" : "<xsl:value-of select="."/>",
    </xsl:template>
    </xsl:stylesheet>

但输出如下:

{    
    "Response" :{            
    "Info" :{            
    "Domain" :"",
    "Source" :""
            },
    "OrderDetails" :{
            "itemNo" : "1 ",
    "OrderNum" :"0002060412",
    "sourceType" :"UTD",
    "organization" :"UTD09",
    "AmtAdjust" :"Not Known-Need Coding"
            },
    "OrderDetails" :{
            "itemNo" : "2 ",
    "OrderNum" :"0002060415",
    "sourceType" :"UTD",
    "organization" :"UTD09",
    "AmtAdjust" :"Not Known-Need Coding"
            },
    "OrderDetails" :{
            "itemNo" : "3 ",
    "OrderNum" :"0002060413",
    "sourceType" :"UTD",
    "organization" :"UTD09",
    "AmtAdjust" :"Not Known-Need Coding"
            },
    "OrderDetails" :{
            "itemNo" : "5 ",
    "OrderNum" :"0060064425",
    "sourceType" :"UTD",
    "organization" :"UTD09",
    "TickNums" :{            
    "TktNum" :"11776564428635"
            },
    "LineDetail" :{            
    "itemNum" :"000010",
    "type" :"ftr",
    "amnt" :"100.000000000 ",
    "qty" :"1.000 ",
    "center" :"0002/0002"
            },
    "LineDetail" :{            
    "itemNum" :"000020",
    "type" :"ert",
    "amnt" :"30.000000000 ",
    "qty" :"1.000 ",
    "center" :"0002/0002"
            },
    "LineDetail" :{            
    "itemNum" :"000030",
    "type" :"VAT",
    "amnt" :"10.000000000 ",
    "qty" :"1.000 ",
    "center" :"0002/0002"
            },
    "LineDetail" :{            
    "itemNum" :"000040",
    "type" :"C2",
    "amnt" :"20.000000000 ",
    "qty" :"1.000 ",
    "center" :"0002/0002"
            },
    "AmtAdjust" :"Not Known-Need Coding"
            },
    "OrderDetails" :{
            "itemNo" : "6 ",
    "OrderNum" :"0060064427",
    "sourceType" :"UTD",
    "organization" :"UTD09",
    "TickNums" :{            
    "TktNum" :"11234569354874"
            },
    "TickNums" :{

    "TktNum" :"45465749854377"
            },
    "LineDetail" :{            
    "itemNum" :"000010",
    "type" :"BR",
    "amnt" :"100.000000000 ",
    "qty" :"1.000 ",
    "center" :"0002/0002"
            },
    "LineDetail" :{            
    "itemNum" :"000020",
    "type" :"ytr",
    "amnt" :"100.000000000 ",
    "qty" :"1.000 ",
    "center" :"0002/0002"
            },
    "LineDetail" :{            
    "itemNum" :"000030",
    "type" :"COMM",
    "amnt" :"200.000000000 ",
    "qty" :"1.000 ",
    "center" :"0002/0002"
            },
    "AmtAdjust" :"Not Known-Need Coding"
            }
            }}

我期待的结果是

    {
    "Response": {
        "Info": {
            "Domain": "",
            "Source": ""
        },
        "OrderDetails": [
            {
                "itemNo": "1 ",
                "OrderNum": "0002060412",
                "sourceType": "UTD",
                "organization": "UTD09",
                "AmtAdjust": "Not Known-Need Coding"
            },
            {
                "itemNo": "2 ",
                "OrderNum": "0002060415",
                "sourceType": "UTD",
                "organization": "UTD09",
                "AmtAdjust": "Not Known-Need Coding"
            },
            {
                "itemNo": "3 ",
                "OrderNum": "0002060413",
                "sourceType": "UTD",
                "organization": "UTD09",
                "AmtAdjust": "Not Known-Need Coding"
            },
            {
                "itemNo": "5 ",
                "OrderNum": "0060064425",
                "sourceType": "UTD",
                "organization": "UTD09",
                "TickNums": {
                    "TktNum": ["11776564428635"]
                },
                "LineDetail": [
                    {
                        "itemNum": "000010",
                        "type": "ftr",
                        "amnt": "100.000000000 ",
                        "qty": "1.000 ",
                        "center": "0002/0002"
                    },
                    {
                        "itemNum": "000020",
                        "type": "ert",
                        "amnt": "30.000000000 ",
                        "qty": "1.000 ",
                        "center": "0002/0002"
                    },
                    {
                        "itemNum": "000030",
                        "type": "VAT",
                        "amnt": "10.000000000 ",
                        "qty": "1.000 ",
                        "center": "0002/0002"
                    },
                    {
                        "itemNum": "000040",
                        "type": "C2",
                        "amnt": "20.000000000 ",
                        "qty": "1.000 ",
                        "center": "0002/0002"
                    }
                ],
                "AmtAdjust": "Not Known-Need Coding"
            },
            {
                "itemNo": "6 ",
                "OrderNum": "0060064427",
                "sourceType": "UTD",
                "organization": "UTD09",
                "TickNums": {
                    "TktNum": [
                        "11234569354874",
                        "45465749854377"
                    ]
                },
                "LineDetail": [
                    {
                        "itemNum": "000010",
                        "type": "BR",
                        "amnt": "100.000000000 ",
                        "qty": "1.000 ",
                        "center": "0002/0002"
                    },
                    {
                        "itemNum": "000020",
                        "type": "ytr",
                        "amnt": "100.000000000 ",
                        "qty": "1.000 ",
                        "center": "0002/0002"
                    },
                    {
                        "itemNum": "000030",
                        "type": "COMM",
                        "amnt": "200.000000000 ",
                        "qty": "1.000 ",
                        "center": "0002/0002"
                    }
                ],
                "AmtAdjust": "Not Known-Need Coding"
            }
        ]
    }
}

但是不能更改输入 xml 以添加更多字段来填充数组.那么如何使用现有的 xslt 更像是一个通用的.

But the input xml can't be changed to add more fields to populate arrays. So how to use the existing xslt as more like a generic one.

如果样式表要为 TktNums 生成一个数组,那么它需要一些额外的信息,而不是从您的输入 XML 提供的信息.它需要某种指令来告诉它 TktNums 可以重复,即使它在这个特定的输入中没有重复.您可以将此信息放在样式表中,但这会妨碍您使样式表完全通用的目标.或者,您可以从模式或您自己发明的某种配置文件中获取它.但它必须来自某个地方.

If the stylesheet is going to generate an array for TktNums, then it needs some extra information beyond what's available from your input XML. It needs some kind of directive to tell it that TktNums can be repeated, even though it isn't repeated in this particular input. You could put this information in the stylesheet, but that would thwart your aim of making the stylesheet completely generic. Alternatively you could get it from a schema, or from some kind of configuration file of your own invention. But it's got to come from somewhere.

在 LineDetail 的情况下,您可以根据子元素重复的事实生成一个数组.但是,在 LineDetail 仅出现一次的输入实例的情况下,这会给您带来问题.

In the case of LineDetail, you could generate an array based on the fact that the child element repeats. But that would give you problems in the case of an input instance where LineDetail only occurs once.

基本上,这不是编码问题,而是设计/规范问题.

Basically, this is not a coding problem but a design/specification problem.