请帮助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>
答案 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/)。
祝你好运, 彼得