XML 使用 XSLT 进行数据透视

XML pivot using XSLT

我收到的 XML 格式如下: -

<Origin>
  <PackageReferenceNumber>
     <Code>0</Code>
     <Value>QAST ROW PKG 01</Value>
  </PackageReferenceNumber>
  <PackageReferenceNumber>
    <Code>33</Code>
    <Value>12345</Value>
  </PackageReferenceNumber>
</Origin>

我想格式化它:

<Origin>
  <PackageReferenceNumber>
    <Code1>0</Code1>
    <Value1>QAST ROW PKG 01</Value1>
    <Code2>33</Code2>
    <Value2>12345</Value2>
  </PackageReferenceNumber>
</Origin>

我正在使用 XSLT 转换 XML。下面是我目前用来转换 XML 的 XSLT 代码。我是 XML 和 XSLT 的新手。任何帮助将不胜感激。

<?xml version="1.0" encoding ="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
<xsl:template match="/">
    <xsl:variable name="var1_initial" select="."/>
    <QuantumViewResponse>
        <xsl:attribute name="xsi:noNamespaceSchemaLocation" namespace="http://www.w3.org/2001/XMLSchema-instance">file:///C:/Users/test.xsd</xsl:attribute>
        <QuantumViewEvents>
            <SubscriptionEvents>
                <SubscriptionFile>
                    <Origin>
                        <xsl:for-each select="QuantumViewResponse/QuantumViewEvents/SubscriptionEvents/SubscriptionFile/Origin/PackageReferenceNumber">
                            <xsl:variable name="var3_current" select="."/>
                            <PackageReferenceNumber>
                                <Code>
                                    <xsl:value-of select="floor(Code)"/>
                                </Code>
                                <Value>
                                    <xsl:value-of select="Value"/>
                                </Value>
                            </PackageReferenceNumber>
                        </xsl:for-each>
                        <xsl:for-each select="QuantumViewResponse/QuantumViewEvents/SubscriptionEvents/SubscriptionFile/Origin">
                            <xsl:variable name="var4_current" select="."/>
                            <TrackingNumber>
                                <xsl:value-of select="TrackingNumber"/>
                            </TrackingNumber>
                        </xsl:for-each>
                    </Origin>
                </SubscriptionFile>
            </SubscriptionEvents>
        </QuantumViewEvents>
    </QuantumViewResponse>
</xsl:template>

我不确定您为什么要以这种方式更改格式。输入 XML 更容易使用!

不过,从您当前的 XSLT 外观来看,您似乎只显示了 XML 的一部分。在这种情况下,最好从身份模板开始

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

然后添加一个模板以匹配 Origin,您在其中创建单个 PackageReferenceNumber,然后 select 所有现有模板。

<xsl:template match="Origin">
  <xsl:copy>
    <PackageReferenceNumber>
      <xsl:apply-templates select="PackageReferenceNumber" />
    </PackageReferenceNumber>
  </xsl:copy>
</xsl:template>

并且在匹配PackageReferenceNumber的模板中你会得到当前的位置,然后在select它的所有子节点之后,你会使用这个位置来改变它们的名字:

<xsl:template match="PackageReferenceNumber">
  <xsl:variable name="pos" select="position()" />
  <xsl:for-each select="*">
    <xsl:element name="{local-name()}{$pos}">
      <xsl:apply-templates select="@*|node()" />
    </xsl:element>
  </xsl:for-each>
</xsl:template>

试试这个 XSLT

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

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

  <xsl:template match="Origin">
    <xsl:copy>
      <PackageReferenceNumber>
        <xsl:apply-templates select="PackageReferenceNumber" />
      </PackageReferenceNumber>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="PackageReferenceNumber">
      <xsl:variable name="pos" select="position()" />
      <xsl:for-each select="*">
        <xsl:element name="{local-name()}{$pos}">
          <xsl:apply-templates select="@*|node()" />
        </xsl:element>
      </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

编辑:为了回应您的评论,一种首选的方法是将对包的引用作为属性。尝试用这个替换最后一个模板:

  <xsl:template match="PackageReferenceNumber">
      <xsl:variable name="pos" select="position()" />
      <xsl:for-each select="*">
        <xsl:copy>
          <xsl:attribute name="ref" select="$pos" />
          <xsl:apply-templates select="@*|node()" />
        </xsl:copy>
      </xsl:for-each>
  </xsl:template>

这会产生以下输出

<Origin>
   <PackageReferenceNumber>
      <Code ref="1">0</Code>
      <Value ref="1">QAST ROW PKG 01</Value>
      <Code ref="2">33</Code>
      <Value ref="2">12345</Value>
   </PackageReferenceNumber>
</Origin>