我有这样的XML:
<assessment name="Assessment">
<section name="Section1">
<item name="Item1-1"/>
<item name="Item1-2"/>
<item name="Item1-3"/>
<item name="Item1-4"/>
<item name="Item1-5"/>
</section>
<section name="Section2">
<item name="Item2-1"/>
<item name="Item2-2"/>
<item name="Item2-3"/>
<section name="Section2-2">
<item name="Item2-2-1"/>
<item name="Item2-2-2"/>
<item name="Item2-2-3"/>
<item name="Item2-2-4"/>
</section>
</section>
</assessment>
如您所见,评估可以包含部分。部分可以包含部分和/或项目。
我想使用XSLT递归计算评估和部分中的项目数。所以,我的转换应该输出这样的东西:
Assessment: 12 items
Section1: 5 items
Section2: 7 items
Section2-2: 4 items
我从这个递归的XSLT开始:
<stylesheet version="2.0" xmlns="http://www.w3.org/1999/XSL/Transform"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<output method="text"/>
<template match="/assessment">
<xsl:for-each select="section">
<xsl:call-template name="sectionCount">
</xsl:call-template>
</xsl:for-each>
</template>
<template name="sectionCount">
<xsl:variable name="items" select="item"/>
<xsl:for-each select="section">
<xsl:call-template name="sectionCount">
</xsl:call-template>
</xsl:for-each>
<xsl:value-of select="count($items)"/>
</template>
</stylesheet>
我无法弄清楚如何将值重新传递并添加它们。这怎么回事呢?
答案 0 :(得分:1)
回答你的问题:你在变量声明中包含对模板的调用。
<xsl:variable name="result">
<!-- call or apply templates here -->
<xsl:call-template name="my-template"/>
</xsl:variable>
<!-- use the defined value: -->
<xsl:copy-of select="$result"/>
但是,在您的情况下,有一种更好的方法可以在嵌套结构中任意深入获取项目总数:使用XPath通配符:
<xsl:value-of select="count(.//item)"/>
您可以这样使用:
<xsl:template match="assessment|section">
<!-- output section subtotal -->
<!-- print name : number-of-items, adapt to get the proper section name -->
<xsl:value-of select="concat(@name, ': ', count(.//item))"/>
<!-- recurse: sub sections will get their subtotals listed, too -->
<xsl:apply-templates select="*"/>
</xsl:template>
答案 1 :(得分:0)
这是一个XSLT 2.0解决方案
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:my="my:my"
>
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="assessment|section">
<xsl:value-of select="concat(@name, ': ', my:sumItems(.), ' items
')"/>
<xsl:apply-templates/>
</xsl:template>
<xsl:function name="my:sumItems" as="xs:integer*">
<xsl:param name="pNode" as="element()"/>
<xsl:sequence select="count($pNode/item) + sum($pNode/section/my:sumItems(.))"/>
</xsl:function>
</xsl:stylesheet>
将此转换应用于提供的XML文档:
<assessment name="Assessment">
<section name="Section1">
<item name="Item1-1"/>
<item name="Item1-2"/>
<item name="Item1-3"/>
<item name="Item1-4"/>
<item name="Item1-5"/>
</section>
<section name="Section2">
<item name="Item2-1"/>
<item name="Item2-2"/>
<item name="Item2-3"/>
<section name="Section2-2">
<item name="Item2-2-1"/>
<item name="Item2-2-2"/>
<item name="Item2-2-3"/>
<item name="Item2-2-4"/>
</section>
</section>
</assessment>
产生了想要的正确结果:
Assessment: 12 items
Section1: 5 items
Section2: 7 items
Section2-2: 4 items
虽然在这个特定的问题中,可以使用简单的XPath表达式(count(.//item)
),此解决方案演示了一个通用且有用的模式,用于不允许立即计算的问题。 / p>