循环遍历XSLT中的节点

时间:2013-08-27 08:40:32

标签: xml xslt

请帮助XSLT,我有这个XML示例

<?xml version="1.0" encoding="utf-8"?>
<Document>
  <TopLevel>
    <Header>
      <!-- Header Information-->
    </Header>
    <!--Payments is a one to many-->
    <Payments>
      <PaymentID>PID1</PaymentID>
      <!--More Info-->
      <!--Transactrion can be one to many for each payment-->
      <Transaction>
        <TranssID>TR1 - PID1</TranssID>
        <TranssID>TR2 - PID1</TranssID>
        <!--More Info-->
      </Transaction>
    </Payments>
    <Payments>
      <PaymentID>PID2</PaymentID>
      <!--More Info-->
      <!--Transactrion can be one to many for each payment-->
      <Transaction>
        <TranssID>TR1 - PID2</TranssID>
        <TranssID>TR2 - PID2</TranssID>
        <!--More Info-->
      </Transaction>
    </Payments>
  </TopLevel>
</Document>

我需要在XSLT中使用循环机制来为每笔付款提供交易。

这是我尝试使用模板方法时的输出 输出:

<?xml version="1.0" encoding="utf-8"?>
<TopLevel>
  <Payments>
    <PaymentID>PID1</PaymentID>
    <transIDs>TR1 - PID1</transIDs>
    <transIDs>TR2 - PID1</transIDs>
    <transIDs>TR1 - PID2</transIDs>
    <transIDs>TR2 - PID2</transIDs>
    <transIDs>TR1 - PID1</transIDs>
    <transIDs>TR2 - PID1</transIDs>
    <transIDs>TR1 - PID2</transIDs>
    <transIDs>TR2 - PID2</transIDs>
  </Payments>
  <Payments>
    <PaymentID>PID1</PaymentID>
    <transIDs>TR1 - PID1</transIDs>
    <transIDs>TR2 - PID1</transIDs>
    <transIDs>TR1 - PID2</transIDs>
    <transIDs>TR2 - PID2</transIDs>
    <transIDs>TR1 - PID1</transIDs>
    <transIDs>TR2 - PID1</transIDs>
    <transIDs>TR1 - PID2</transIDs>
    <transIDs>TR2 - PID2</transIDs>
  </Payments>
</TopLevel>

我希望它按交易和付款分开

这是我的XSLT

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/">
    <TopLevel>
      <xsl:apply-templates select="//TopLevel/Payments"/>
    </TopLevel>
  </xsl:template>

  <xsl:template match="//TopLevel/Payments">
    <Payments>
      <PaymentID>
        <xsl:value-of select="//TopLevel/Payments/PaymentID"/>
      </PaymentID>
      <xsl:apply-templates select="//TopLevel/Payments/Transaction"/>
    </Payments>
  </xsl:template>

  <xsl:template match="//TopLevel/Payments/Transaction">
    <xsl:apply-templates select="//TopLevel/Payments/Transaction/TranssID"/>
  </xsl:template>

  <xsl:template match="//TopLevel/Payments/Transaction/TranssID">
    <transIDs>
      <xsl:value-of select="."/>
    </transIDs>
  </xsl:template>

</xsl:stylesheet>

2 个答案:

答案 0 :(得分:1)

您的问题是您在/apply-templates指令中使用绝对路径(带有前导value-of)的方式。例如

<xsl:apply-templates select="//TopLevel/Payments/Transaction"/>

会将模板应用于整个文档中所有 Transaction元素中的所有 Payments元素。这就是您每次都看到TranssID每个//的原因。您应该使用相对路径,这样您只能从当前使用的元素中提取子元素,并且除非真的有必要,否则您应该避免使用<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="xml" indent="yes"/> <xsl:template match="/"> <TopLevel> <xsl:apply-templates select="Document/TopLevel/Payments"/> </TopLevel> </xsl:template> <xsl:template match="Payments"> <Payments> <PaymentID> <xsl:value-of select="PaymentID"/> </PaymentID> <xsl:apply-templates select="Transaction"/> </Payments> </xsl:template> <xsl:template match="Transaction"> <xsl:apply-templates select="TranssID"/> </xsl:template> <xsl:template match="TranssID"> <transIDs> <xsl:value-of select="."/> </transIDs> </xsl:template> </xsl:stylesheet> ,原因是效率:

match

另请注意,模板{{1}}表达式不需要返回根目录的完整路径,它们只需要足够的细节来消除模板之间的歧义。在您的情况下,您处理的所有不同元素都有不同的名称,因此单个元素名称足以匹配。

答案 1 :(得分:0)

你有没有尝试过任何东西?在使用<xsl:for-each>之前,您应该使用<xsl:apply-templates>构造(另请参阅:For loops vs. apply-templates)。

如果您应用此XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">

<xsl:output method="xml" indent="yes"/>

<xsl:template match="/">
    <list>
        <xsl:apply-templates select="//Payments"/>
    </list>
</xsl:template>

<xsl:template match="Payments">
        <xsl:apply-templates select="Transaction"/>
</xsl:template>

<xsl:template match="Transaction">
    <xsl:apply-templates select="TranssID"/>
</xsl:template>

<xsl:template match="TranssID">
    <transIDs>
        <xsl:value-of select="."/>
    </transIDs>
</xsl:template>

</xsl:stylesheet>

到您的源XML,您将获得此输出:

<?xml version="1.0" encoding="UTF-8"?>
<list>
 <transIDs>TR1 - PID1</transIDs>
 <transIDs>TR2 - PID1</transIDs>
 <transIDs>TR1 - PID2</transIDs>
 <transIDs>TR2 - PID2</transIDs>
</list>

当然还有其他方法可以做到这一点。试试吧。也不要使用w3schools.com,看看为什么(http://www.w3fools.com/)。

祝你好运, 彼得