使用XSLT进行XML转换

时间:2015-04-07 08:09:18

标签: xml xslt

我正在尝试使用XSLT转换XML。以下是我的XML结构:

<?xml version="1.0" encoding="UTF-8"?>
<GetInvoiceList>
<Request>
<BillStatusCode typecode="1">type description</BillStatusCode>
<EBillProcessStatusCode typecode="2">type description</EBillProcessStatusCode>
</Request>
</GetInvoiceList>

我尝试了这个XSLT代码:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:template match="node()">
<xsl:copy>
<xsl:element name="{name()}">
<xsl:apply-templates select="node()"/>
</xsl:element>
<xsl:apply-templates select="@*"/>
</xsl:copy>
</xsl:template>

<xsl:template match="@*">
<xsl:element name="{name()}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>

输出:

<GetInvoiceList>
<GetInvoiceList>
    <Request>
        <Request>
            <BillStatusCode>
                <BillStatusCode>type description</BillStatusCode>
                <typecode>1</typecode>
            </BillStatusCode>
            <EBillProcessStatusCode>
                <EBillProcessStatusCode>type description</EBillProcessStatusCode>
                <typecode>2</typecode>
            </EBillProcessStatusCode>
        </Request>
    </Request>
</GetInvoiceList>
</GetInvoiceList>

预期产出:

  <GetInvoiceList>
       <Request>
                <BillStatusCode>
                <BillStatusCode>type description</BillStatusCode>
                <typecode>1</typecode>
            </BillStatusCode>
            <EBillProcessStatusCode>
                <EBillProcessStatusCode>type description</EBillProcessStatusCode>
                <typecode>2</typecode>
            </EBillProcessStatusCode>
        </Request>
        </GetInvoiceList>

代码正在处理所有节点,这就是创建重复节点的原因。我希望它只适用于那些有文本和文本的节点。属性。

感谢任何有关此事的帮助。谢谢!

1 个答案:

答案 0 :(得分:0)

问题出在node()匹配模板中;你有一个xsl:copy和一个xsl:element,它们都创建了相同的元素,导致重复。这适用于所有节点

<xsl:template match="node()">
   <xsl:copy>
       <xsl:element name="{name()}">

您需要将此更改为仅匹配具有属性的元素

<xsl:template match="*[@*]">
   <xsl:copy>
      <xsl:copy>
         <xsl:apply-templates select="node()"/>
      </xsl:copy>
      <xsl:apply-templates select="@*"/>
    </xsl:copy>
</xsl:template>

然后,您有一个仅与node()匹配的模板,您可以在其中删除xsl:element元素

<xsl:template match="node()">
   <xsl:copy>
      <xsl:apply-templates select="node()"/>
   </xsl:copy>
</xsl:template>

试试这个XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="node()">
        <xsl:copy>
            <xsl:apply-templates select="node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="*[@*]">
        <xsl:copy>
            <xsl:copy>
                <xsl:apply-templates select="node()"/>
            </xsl:copy>
            <xsl:apply-templates select="@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="@*">
        <xsl:element name="{name()}">
        <xsl:value-of select="."/>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>