从XML转换为JSON时,使用XSLT从JSON中删除额外标记

时间:2015-06-01 10:42:03

标签: json xml xslt

我是XSLT的新手。使用XSLT将XML转换为JSON时遇到问题。

XML输入

<ArrayOfApiInvoiceReport>
<ApiInvoiceReport>
    <BillingAddress1>9055 LOCUST ST STE B10</BillingAddress1>
    <BillingAddress2/>
    <BillingCity>ELK GROVE</BillingCity>
    <BillingCountry>US</BillingCountry>
    <InvoiceItems>
        <InvoiceItemSizes>
            <InvoiceLineNumber>1</InvoiceLineNumber>
            <InvoicedQuantity>2</InvoicedQuantity>
        </InvoiceItemSizes>
        <InvoiceLineNumber>1</InvoiceLineNumber>
        <InvoiceNumber>101000001</InvoiceNumber>
    </InvoiceItems>
    <InvoiceItems>
        <InvoiceItemSizes>
            <InvoiceLineNumber>2</InvoiceLineNumber>
            <InvoicedQuantity>2</InvoicedQuantity>
        </InvoiceItemSizes>
        <InvoiceLineNumber>2</InvoiceLineNumber>
        <InvoiceNumber>101000001</InvoiceNumber>
    </InvoiceItems>
    <InvoiceNumber>101000001</InvoiceNumber>
    <InvoiceSentDate>20141109</InvoiceSentDate>
    <InvoiceStatus>95</InvoiceStatus>
</ApiInvoiceReport>
<ApiInvoiceReport>
    <BillingAddress1>9055 LOCUST ST STE B10</BillingAddress1>
    <BillingAddress2/>
    <BillingCity>ELK GROVE</BillingCity>
    <BillingCountry>US</BillingCountry>

    <InvoiceItems>
        <InvoiceItemSizes>
            <InvoiceLineNumber>1</InvoiceLineNumber>
            <InvoicedQuantity>2</InvoicedQuantity>
        </InvoiceItemSizes>
        <InvoiceLineNumber>1</InvoiceLineNumber>
        <InvoiceNumber>101000002</InvoiceNumber>
    </InvoiceItems>
    <InvoiceNumber>101000002</InvoiceNumber>
    <InvoiceSentDate>20141109</InvoiceSentDate>
    <InvoiceStatus>95</InvoiceStatus>
</ApiInvoiceReport>
</ArrayOfApiInvoiceReport>

输出JSON

[{
"ApiInvoiceReport": [
  {
    "BillingAddress1": "9055 LOCUST ST STE B10",
    "BillingAddress2": "",
    "BillingCity": "ELK GROVE",
    "BillingCountry": "US",
    "InvoiceItems": [
      {
        "InvoiceItemSizes": [
          {
            "InvoiceLineNumber": "1",
            "InvoicedQuantity": "2"
          }
        ],
        "InvoiceLineNumber": "1",
        "InvoiceNumber": "101000001"
      },
      {
        "InvoiceItemSizes": [
          {
            "InvoiceLineNumber": "2",
            "InvoicedQuantity": "2"
          }
        ],
        "InvoiceLineNumber": "2",
        "InvoiceNumber": "101000001"
      }
    ],
    "InvoiceNumber": "101000001",
    "InvoiceSentDate": "20141109",
    "InvoiceStatus": "95"
  },
  {
    "BillingAddress1": "9055 LOCUST ST STE B10",
    "BillingAddress2": "",
    "BillingCity": "ELK GROVE",
    "BillingCountry": "US",
    "InvoiceItems": [
      {
        "InvoiceItemSizes": [
          {
            "InvoiceLineNumber": "1",
            "InvoicedQuantity": "2"
          }
        ],
        "InvoiceLineNumber": "1",
        "InvoiceNumber": "101000002"
      }
    ],
    "InvoiceNumber": "101000002",
    "InvoiceSentDate": "20141109",
    "InvoiceStatus": "95"
  }
]  }]

使用XSLT

<?xml version="1.0" encoding="UTF-8"?><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output encoding="utf-8" method="text" omit-xml-declaration="yes"/>
<xsl:variable name="nl">
    <xsl:text/>
</xsl:variable>
<xsl:variable name="tb">
    <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 mode="detect" select="*">
        <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="detect">
    <xsl:choose>
        <xsl:when test="name(preceding-sibling::*[1]) = name(current()) and name(following-sibling::*[1]) != name(current())">
            <xsl:apply-templates mode="obj-content" select="."/>
            <xsl:text>]</xsl:text>
            <xsl:if test="count(following-sibling::*[name() != name(current())]) > 0">, </xsl:if>
        </xsl:when>
        <xsl:when test="name(preceding-sibling::*[1]) = name(current())">
            <xsl:apply-templates mode="obj-content" select="."/>
            <xsl:if test="name(following-sibling::*) = name(current())">, </xsl:if>
        </xsl:when>
        <xsl:when test="following-sibling::*[1][name() = name(current())]">
            <xsl:text>"</xsl:text>
            <xsl:value-of select="name()"/>
            <xsl:text>" : [</xsl:text>
            <xsl:apply-templates mode="obj-content" select="."/>
            <xsl:text>, </xsl:text>
        </xsl:when>
        <xsl:when test="count(./child::*) > 0 or count(@*) > 0">
            <xsl:text>"</xsl:text>
            <xsl:value-of select="name()"/>" : [<xsl:apply-templates
                mode="obj-content" select="."/>
            <xsl:if test="count(following-sibling::*) > 0">], </xsl:if>
        </xsl:when>
        <xsl:when test="count(./child::*) = 0">
            <xsl:text>"</xsl:text>
            <xsl:value-of select="name()"/>" : "<xsl:apply-templates select="."/>
            <xsl:text>"</xsl:text>
            <xsl:if test="count(following-sibling::*) > 0">, </xsl:if>
        </xsl:when>
    </xsl:choose>
</xsl:template>
<xsl:template match="*" mode="obj-content">
    <xsl:text>{</xsl:text>
    <xsl:apply-templates mode="attr" select="@*"/>
    <xsl:if test="count(@*) > 0 and (count(child::*) > 0 or text())">, </xsl:if>
    <xsl:apply-templates mode="detect" select="./*"/>
    <xsl:if test="count(child::*) = 0 and text() and not(@*)">
        <xsl:text>"</xsl:text>
        <xsl:value-of select="name()"/>" : "<xsl:value-of select="text()"/>
        <xsl:text>"</xsl:text>
    </xsl:if>
    <xsl:if test="count(child::*) = 0 and text() and @*">
        <xsl:text>: "</xsl:text>
        <xsl:value-of select="text()"/>
        <xsl:text>"</xsl:text>
    </xsl:if>
    <xsl:text>}</xsl:text>
    <xsl:if test="position() &lt; last()">, </xsl:if>
</xsl:template>
<xsl:template match="@*" mode="attr">
    <xsl:text>"</xsl:text>
    <xsl:value-of select="name()"/>" : "<xsl:value-of select="."/>
    <xsl:text>"</xsl:text>
    <xsl:if test="position() &lt; last()">,</xsl:if>
</xsl:template>
<xsl:template match="node/@TEXT | text()" name="removeBreaks">
    <xsl:param name="pText" select="normalize-space(.)"/>
    <xsl:choose>
        <xsl:when test="not(contains($pText, '&#xa;'))">
            <xsl:copy-of select="$pText"/>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="concat(substring-before($pText, '&#xd;&#xa;'), ' ')"/>
            <xsl:call-template name="removeBreaks">
                <xsl:with-param name="pText" select="substring-after($pText, '&#xd;&#xa;')"/>
            </xsl:call-template>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>
</xsl:stylesheet>

需要输出

[
  {
    "BillingAddress1": "9055 LOCUST ST STE B10",
    "BillingAddress2": "",
    "BillingCity": "ELK GROVE",
    "InvoiceItems": [
      {
        "InvoiceItemSizes": [
          {
            "InvoiceLineNumber": "1",
            "InvoicedQuantity": "2",
            "SizeCode": "1SZ",
            "UPC": "9343744951476"
          }
        ],
        "InvoiceLineNumber": "1",
        "InvoiceNumber": "101000001",
        "InvoicedQuantity": "2",
        "ProductInvoicedPrice": "100.00",
        "ProductName": "K38 TIDEMASTER SILICONE",
        "ProductNumber": "A1103BLK1SZ"
      },
      {
        "InvoiceItemSizes": [
          {
            "InvoiceLineNumber": "2",
            "InvoicedQuantity": "2",
            "SizeCode": "1SZ",
            "UPC": "9343744054450"
          }
        ],
        "InvoiceLineNumber": "2",
        "InvoiceNumber": "101000001",
        "InvoicedQuantity": "2",
        "ProductInvoicedPrice": "40.00",
        "ProductName": "PIVOT PU",
        "ProductNumber": "A2410BLK1SZ"
      }
    ],
    "ShippingAddress1": "9055 LOCUST ST STE B10",
    "ShippingAddress2": "",
    "ShippingCity": "ELK GROVE"
  },
  {
    "BillingAddress1": "9055 LOCUST ST STE B10",
    "BillingAddress2": "",
    "BillingCity": "ELK GROVE",
    "InvoiceItems": [
      {
        "InvoiceItemSizes": [
          {
            "InvoiceLineNumber": "1",
            "InvoicedQuantity": "2",
            "SizeCode": "1SZ",
            "UPC": "9348282068914"
          }
        ],
        "InvoiceLineNumber": "1",
        "InvoiceNumber": "101000002",
        "InvoicedQuantity": "2",
        "ProductInvoicedPrice": "45.00",
        "ProductName": "CANDY DIGITAL",
        "ProductNumber": "A2466GWHI1SZ"
      }
    ],
    "ShippingAddress1": "9055 LOCUST ST STE B10",
    "ShippingAddress2": "",
    "ShippingCity": "ELK GROVE"
  }
]`

从JSON输出中我们只需要删除ApiInvoiceReport标记。 我试图解决这个问题但我做不到。

1 个答案:

答案 0 :(得分:0)

一个解决方案可能是(不是最优雅的)。改变下一个:

    <xsl:when test="following-sibling::*[1][name() = name(current())]">
        <xsl:text>"</xsl:text>
        <xsl:value-of select="name()"/>
        <xsl:text>" : [</xsl:text>
        <xsl:apply-templates mode="obj-content" select="."/>
        <xsl:text>, </xsl:text>
    </xsl:when>

要:

    <xsl:when test="following-sibling::*[1][name() = name(current())]">
        <xsl:choose>
            <xsl:when test="local-name(current()) = 'ApiInvoiceReport'">
                <xsl:apply-templates mode="detect" select="*"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:text>"</xsl:text>
                <xsl:value-of select="name()"/>
                <xsl:text>" : [</xsl:text>
                <xsl:apply-templates mode="obj-content" select="."/>
                <xsl:text>, </xsl:text>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:when>