需要XSL转换帮助

时间:2014-04-21 21:32:37

标签: xml xslt

我已经浏览过互联网,但却无法弄清楚如何做到这一点。 本质上,我需要重命名根元素,并将所有节点包装在某些标签中。 请看下面。 谢谢你的帮助!

实际Xml

    <?xml version="1.0" encoding="utf-8"?>
    <RefundInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <header>
        <cell>TBD</cell>
        <client>TBD</client>
        <notification_address>TBD</notification_address>
        <password>TBD</password>
        <source>TBD</source>
        <target>TBD</target>
        <version>TBD</version>
      </header>
      <ImageHost>NotImplemented</ImageHost>
      <OriginalOrder>
        <AmountCharged>26.5000</AmountCharged>
        <AmountChargedLessFees>24.0000</AmountChargedLessFees>
        <Fees>0</Fees>
        <Movie>
          <ShowTime>2012-05-05T15:45:00</ShowTime>
          <Title>Marvel's The Avengers 3D</Title>
        </Movie>
        <Theater>
          <Name>Regal Arroyo Grande Stadium 10</Name>
        </Theater>
        <Tickets>
          <Ticket>
            <Description>3D Matinee</Description>
            <Quantity>1</Quantity>
          </Ticket>
          <Ticket>
            <Description>3D Child</Description>
            <Quantity>1</Quantity>
          </Ticket>
        </Tickets>
        <Total>0</Total>
        <TransactionID></TransactionID>
      </OriginalOrder>
      <RefundOrder>
        <PaymentInstruments>
          <PaymentInstrument>
            <ItemType>Credit Card</ItemType>
            <ItemCode />
            <Amount>-1.5000</Amount>
          </PaymentInstrument>
          <PaymentInstrument>
            <ItemType>Promotion Codes</ItemType>
            <ItemCode />
            <Amount>-25.0000</Amount>
          </PaymentInstrument>
        </PaymentInstruments>
        <TransactionID></TransactionID>
      </RefundOrder>
    </RefundInfo>

必需的Xml

    <?xml version="1.0" encoding="utf-8"?>
    <request xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <header>
        <cell>TBD</cell>
        <client>TBD</client>
        <notification_address>TBD</notification_address>
        <password>TBD</password>
        <source>TBD</source>
        <target>TBD</target>
        <version>TBD</version>
      </header>
      <data>
        <row>
          <ImageHost>NotImplemented</ImageHost>
          <OriginalOrder>
            <AmountCharged>26.5000</AmountCharged>
            <AmountChargedLessFees>24.0000</AmountChargedLessFees>
            <Fees>0</Fees>
            <Movie>
              <ShowTime>2012-05-05T15:45:00</ShowTime>
              <Title>Marvel's The Avengers 3D</Title>
            </Movie>
            <Theater>
              <Name>Regal Arroyo Grande Stadium 10</Name>
            </Theater>
            <Tickets>
              <Ticket>
                <Description>3D Matinee</Description>
                <Quantity>1</Quantity>
              </Ticket>
              <Ticket>
                <Description>3D Child</Description>
                <Quantity>1</Quantity>
              </Ticket>
            </Tickets>
            <Total>0</Total>
            <TransactionID></TransactionID>
          </OriginalOrder>
          <RefundOrder>
            <PaymentInstruments>
              <PaymentInstrument>
                <ItemType>Credit Card</ItemType>
                <ItemCode />
                <Amount>-1.5000</Amount>
              </PaymentInstrument>
              <PaymentInstrument>
                <ItemType>Promotion Codes</ItemType>
                <ItemCode />
                <Amount>-25.0000</Amount>
              </PaymentInstrument>
            </PaymentInstruments>
            <TransactionID></TransactionID>
          </RefundOrder>
        </row>
      </data>
    </request>

到目前为止,它有效,但我知道这是做错的方法

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

      <!--Remove empty lines-->
      <xsl:strip-space  elements="*"/>

      <!--Remove Empty Nodes-->
      <xsl:template match="*[not(child::node())]"/>

      <!--Get All Summary Fields-->
      <xsl:variable name="dataRow" select="//OriginalOrder|//RefundOrder|//ImageHost" />

      <xsl:template match="/">
        <request xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
          <xsl:copy-of select="//header"/>
          <data>
            <row>
              <xsl:for-each select="$dataRow">
                <xsl:copy>
                  <xsl:copy-of select="node()|@*"/>
                </xsl:copy>
              </xsl:for-each>
            </row>
          </data>
        </request>
      </xsl:template>
    </xsl:stylesheet>

1 个答案:

答案 0 :(得分:0)

这里有3种方法。您可以使用for-each提取节点,使用apply-templates推送方法或两者的组合。有很多方法可以做你想要的。以下是组合方法的一个示例:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" encoding="utf-8" indent="yes"/>
    <!--Remove empty lines-->
    <xsl:strip-space elements="*"/>
    <!--Remove Empty Nodes-->
    <xsl:template match="*[not(child::node())]"/>
    <!--Get All Summary Fields-->
    <xsl:template match="/">
        <request>
            <xsl:apply-templates select="/RefundInfo/header"/>
            <data>
                <row>
                    <xsl:for-each select="//OriginalOrder|//RefundOrder|//ImageHost">
                        <xsl:copy>
                            <xsl:copy-of select="@*"/>
                            <xsl:apply-templates/>
                        </xsl:copy>
                    </xsl:for-each>
                </row>
            </data>
        </request>
    </xsl:template>
    <xsl:template match="*">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template> 
</xsl:stylesheet>

这是完整的推送方式:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" encoding="utf-8" indent="yes"/>
    <!--Remove empty lines-->
    <xsl:strip-space elements="*"/>
    <!--Remove Empty Nodes-->
    <xsl:template match="*[not(child::node())]"/>
    <!--Get All Summary Fields-->
    <xsl:template match="/">
        <request>
            <xsl:apply-templates select="/RefundInfo/header"/>
            <data>
                <row>
                    <xsl:apply-templates select="//OriginalOrder|//RefundOrder|//ImageHost"/>
                </row>
            </data>
        </request>
    </xsl:template>
    <xsl:template match="*">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

你的方式有效,但不是很漂亮。例如,您创建了一个名为dataRow的变量,它不需要保存xpath值。您只需将xpath称为//OriginalOrder|//RefundOrder|//ImageHost即可。

使用//后跟节点名称选择具有该名称的所有节点,无论它们在xml中的位置如何。如果这不是问题,那么它很好,但可能是一个问题。