【问题标题】:Remove root tag in JSON using XSLT when converting XML to JSON将 XML 转换为 JSON 时使用 XSLT 删除 JSON 中的根标记
【发布时间】:2015-05-26 06:02:52
【问题描述】:

我正在尝试使用 XSLT 定义将 XML 转换为 JSON。我已经得到了所需的输出,但我希望在转换时从我的 json 输出中删除一个根标记,请帮我解决这个问题。

XML 输入

<ArrayOfApiInvoiceReport xmlns="http://schemas.datacontract.org/2004/07/RepSpark.WebServices.Models">
    <BillingAddress1>10 N LUMINA AVE</BillingAddress1>
    <BillingAddress2/>
    <BillingCity>WRIGHTSVILLE BEACH</BillingCity>
    <BillingCountry>US</BillingCountry>
    <BillingCustomerCode>3003800</BillingCustomerCode>
    <BillingCustomerName>SWEETWATER SURF SHOP</BillingCustomerName>
    <BillingState>NC</BillingState>
    <BillingZip>28480</BillingZip>
    <InvoiceAmount>372.72</InvoiceAmount>
    <InvoiceCreatedDate>20141110</InvoiceCreatedDate>
    <InvoiceItems>
        <InvoiceItemSizes>
            <InvoiceLineNumber>1</InvoiceLineNumber>
            <InvoicedQuantity>3</InvoicedQuantity>
            <SizeCode>L</SizeCode>
            <UPC>9348282095644</UPC>
        </InvoiceItemSizes>
        <InvoiceLineNumber>1</InvoiceLineNumber>
        <InvoiceNumber>101000005</InvoiceNumber>
    <InvoiceItems>
</ArrayOfApiInvoiceReport

使用 XSLT

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

<!-- Object or Element Property-->
<xsl:template match="*">
    <xsl:call-template name="Properties"/>
</xsl:template>

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

<!-- Object Properties -->
<xsl:template name="Properties">
    <xsl:variable name="childName" select="name(*[1])"/>
    <xsl:choose>
        <xsl:when test="not(*|@*)">"<xsl:value-of select="."/>"</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>

当前 JSON 输出

"ArrayOfApiInvoiceReport" : [{

    "BillingAddress1" : "10 N LUMINA AVE",
    "BillingAddress2" : "",
    "BillingCity" : "WRIGHTSVILLE BEACH",
    "BillingCountry" : "US",
    "BillingCustomerCode" : "3003800",
    "BillingCustomerName" : "SWEETWATER SURF SHOP",
    "BillingState" : "NC",
    "BillingZip" : "28480",
    "InvoiceAmount" : "372.72",
    "InvoiceCreatedDate" : "20141110",
    "InvoiceItems" : [{

    "InvoiceItemSizes" : [{

    "InvoiceLineNumber" : "1",
    "InvoicedQuantity" : "3",
    "SizeCode" : "L",
    "UPC" : "9348282095644"
}],
    "InvoiceLineNumber" : "1",
    "InvoiceNumber" : "101000005",
    "InvoicedQuantity" : "3",

必需的输出是没有"ArrayOfApiInvoiceReport"[{

的JSON
"BillingAddress1": "10 N LUMINA AVE",
"BillingAddress2": "",
"BillingCity": "WRIGHTSVILLE BEACH",
"BillingCountry": "US",
"BillingCustomerCode": "3003800",
"BillingCustomerName": "SWEETWATER SURF SHOP",
"BillingState": "NC",
"BillingZip": "28480",
"InvoiceAmount": "372.72",
"InvoiceCreatedDate": "20141110",
"InvoiceItems": [
  {
    "InvoiceItemSizes": [
      {
        "InvoiceLineNumber": "1",
        "InvoicedQuantity": "3",
        "SizeCode": "L",
        "UPC": "9348282095644"
      }
    ],
    "InvoiceLineNumber": "1",
    "InvoiceNumber": "101000005",
    "InvoicedQuantity": "3",

请帮帮我。

【问题讨论】:

  • 所需的输出没有“ArrayOfApiInvoiceReport”。输出应以 [{"BillingAddress1": "10 N ................}] 开头
  • Siva,我对你的问题有几点看法。 XML 无效,因为“InvoiceItems”节点错误关闭;在输出 JSON 上,“InvoiceItems”没有闭包;末尾有一个额外的“InvoicedQuantity”,输入 XML 中没有相应的元素 - 这是计算出来的吗? JSON 以逗号结尾 - 这就是你想要的吗?

标签: json xml xslt


【解决方案1】:

请参阅我对原始问题的观点。

这是一个将 XML 转换为 JSON 而没有包含节点的样式表。

这个样式表也省略了最后的逗号。如果你想保留它,你需要添加它。

  <xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 

   >


                <xsl:output method="text" />
                <xsl:variable name="nl"><xsl:text>&#xa;</xsl:text></xsl:variable>
                <xsl:variable name="tb"><xsl:text>&#x9;</xsl:text></xsl:variable>

                <xsl:template match="/*">


                    <!-- Open the root array -->
                    <xsl:text>[{</xsl:text>
                    <xsl:value-of select="$nl" />

                    <!-- Process all the child nodes of the root -->
                    <xsl:apply-templates select="*" mode="subitem" >
                        <xsl:with-param name="indent" select="$tb" />
                    </xsl:apply-templates>

                    <!-- Close the root array -->
                    <xsl:value-of select="$nl" />
                    <xsl:text>}]</xsl:text>


                </xsl:template>




                <xsl:template match="*" mode="subitem" >
                    <!-- child element at any level. The indent parameter allows for better layout of the output JSON -->
                    <xsl:param name="indent"></xsl:param>

                    <!-- newindent is used as the indent for children of this node -->
                    <xsl:variable name="newindent"><xsl:value-of select="$indent" /><xsl:value-of select="$tb"/></xsl:variable>

                    <!-- output the name of this node in quotes, ready for the content to follow -->
                    <xsl:value-of select="$indent" /><xsl:text>"</xsl:text><xsl:value-of select="name()" /><xsl:text>" :</xsl:text>

                    <!-- check if this node has children, if not, simply output the text value, otherwise outoput an array -->
                    <xsl:choose>
                        <xsl:when test=" count( ./* ) = 0 ">
                            <!-- This is a text value only -->
                                <xsl:text> "</xsl:text>

                                <!-- Make sure that any embedded quotes are escaped -->
                                <xsl:call-template name="string-replace-all">
                                    <xsl:with-param name="text" select="." />
                                    <xsl:with-param name="replace">"</xsl:with-param>
                                    <xsl:with-param name="by">\"</xsl:with-param>

                                </xsl:call-template>
                                <xsl:text>"</xsl:text>

                                <!-- check if we need a comma and a new line, not required if this is the last output value -->
                                <xsl:if test=" position() != last() ">
                                    <xsl:text>,</xsl:text>
                                    <xsl:value-of select="$nl" />
                                </xsl:if>
                        </xsl:when>
                        <xsl:otherwise>
                            <!-- This node has children, so we need to process them as an array -->

                                <!-- Array opening -->
                                <xsl:text>[</xsl:text><xsl:value-of select="$nl" />
                                <xsl:value-of select="$newindent" /><xsl:text>{</xsl:text><xsl:value-of select="$nl" />

                                    <!-- Process all the elements in the array (recursive call to this template) -->
                                    <xsl:apply-templates select="*" mode="subitem" >
                                        <xsl:with-param name="indent"><xsl:value-of select="$newindent" /></xsl:with-param>
                                    </xsl:apply-templates>

                                <!-- Close the array -->
                                <xsl:value-of select="$nl" /><xsl:value-of select="$newindent" /><xsl:text>}</xsl:text>
                                <xsl:value-of select="$nl" /><xsl:value-of select="$indent" /><xsl:text>]</xsl:text>

                                <!-- If this is not the last node then we need a comma and line feed -->
                                <xsl:if test=" position() != last() ">
                                    <xsl:text>,</xsl:text>
                                    <xsl:value-of select="$nl" />
                                </xsl:if>

                        </xsl:otherwise>

                    </xsl:choose>

                </xsl:template>


                <xsl:template name="string-replace-all">
                <!-- This code provided thanks to @codesling on stackoverflow -->
                  <xsl:param name="text" />
                  <xsl:param name="replace" />
                  <xsl:param name="by" />
                  <xsl:choose>
                    <xsl:when test="contains($text, $replace)">
                      <xsl:value-of select="substring-before($text,$replace)" />
                      <xsl:value-of select="$by" />
                      <xsl:call-template name="string-replace-all">
                        <xsl:with-param name="text"
                        select="substring-after($text,$replace)" />
                        <xsl:with-param name="replace" select="$replace" />
                        <xsl:with-param name="by" select="$by" />
                      </xsl:call-template>
                    </xsl:when>
                    <xsl:otherwise>
                      <xsl:value-of select="$text" />
                    </xsl:otherwise>
                  </xsl:choose>
                </xsl:template>

    </xsl:stylesheet>

使用(更正的)XML 输出是:

 [{
    "BillingAddress1" : "10 N LUMINA AVE",
    "BillingAddress2" : "",
    "BillingCity" : "WRIGHTSVILLE BEACH",
    "BillingCountry" : "US",
    "BillingCustomerCode" : "3003800",
    "BillingCustomerName" : "SWEETWATER SURF SHOP",
    "BillingState" : "NC",
    "BillingZip" : "28480",
    "InvoiceAmount" : "372.72",
    "InvoiceCreatedDate" : "20141110",
    "InvoiceItems" :[
        {
        "InvoiceItemSizes" :[
            {
            "InvoiceLineNumber" : "1",
            "InvoicedQuantity" : "3",
            "SizeCode" : "L",
            "UPC" : "9348282095644"
            }
        ],
        "InvoiceLineNumber" : "1",
        "InvoiceNumber" : "101000005"
        }
    ]
}]      

【讨论】:

  • 在上面的示例中,我们在 InvoiceItem 级别中只有一项。如果当我们将 xml 转换为 json 时,我们会在单个 [] 中获取项目。同样的情况,如果我们有多个项目,我得到的输出为
  • 在上面的示例中,我们在 InvoiceItem 级别中只有一项。如果当我们将 xml 转换为 json 时,我们会在单个 [] 中获取项目。同样的情况,如果我们有多个项目,我将输出为“InvoiceItem”:[{ }]、“InvoiceItem”:[{}]、“InvoiceItems”:[{}]。我希望它像 "InvoiceItem" : [{}, {}, {}] 我不希望它有多个 InvoiceItem 标签。输入 xml 看起来像 。我需要根据需要使用 XSLT 来获取它,因为我无法更改 XML。请帮帮我。
  • 您能帮我删除我粘贴的 xslt 中的 Root 元素吗?提前致谢!
  • @SivaSwarna XML 中的 节点在哪里?示例 XML 中没有。请提供一个示例 XML,其中包含多个 节点,完全符合您的预期。
猜你喜欢
  • 2015-08-14
  • 2021-02-20
  • 2020-01-26
  • 2023-03-30
  • 1970-01-01
  • 1970-01-01
  • 2014-06-09
  • 2019-12-28
相关资源
最近更新 更多