对于以下交叉引用,我建议设置键,然后,为了解决问题,递归是解决方案的关键(另一个),因此在XSLT 2或3中,可以使用递归函数来实现这一点:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:mf="http://example.com/mf"
exclude-result-prefixes="xs mf"
version="3.0">
<xsl:param name="start-id">7</xsl:param>
<xsl:key name="id" match="item" use="@id"/>
<xsl:key name="child" match="item" use="parent/@idref"/>
<xsl:function name="mf:descendants" as="element(item)*">
<xsl:param name="item" as="element(item)*"/>
<xsl:sequence
select="let $children := key('child', $item/@id, root($item))
return ($children | $children!mf:descendants(.))"/>
</xsl:function>
<xsl:template match="/">
<xsl:value-of select="count(mf:descendants(key('id', $start-id)))"/>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/bdxtpH/0
和
https://xsltfiddle.liberty-development.net/bdxtpH/1
和
https://xsltfiddle.liberty-development.net/bdxtpH/2
下面是一些例子。
对于XSLT 2,您将使用本地
xsl:variable
而不是
let $children
以上使用:
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:mf="http://example.com/mf"
exclude-result-prefixes="xs mf">
<xsl:param name="start-id">1</xsl:param>
<xsl:key name="id" match="item" use="@id"/>
<xsl:key name="child" match="item" use="parent/@idref"/>
<xsl:function name="mf:descendants" as="element(item)*">
<xsl:param name="item" as="element(item)*"/>
<xsl:variable name="children" select="key('child', $item/@id, root($item))"/>
<xsl:sequence
select="$children | $children/mf:descendants(.)"/>
</xsl:function>
<xsl:template match="/">
<xsl:value-of select="count(mf:descendants(key('id', $start-id)))"/>
</xsl:template>
</xsl:transform>
http://xsltransform.hikmatu.com/pPgCcou
对于XSLT 1,您可以使用一种稍微不同的方法,使用一个递归的命名模板来收集子体,直到它找不到更多的子体,然后输出计数:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:param name="start-id">7</xsl:param>
<xsl:key name="id" match="item" use="@id"/>
<xsl:key name="child" match="item" use="parent/@idref"/>
<xsl:template name="count-descendants">
<xsl:param name="descendants" select="/.."/>
<xsl:param name="level"/>
<xsl:variable name="children" select="key('child', $level/@id)"/>
<xsl:choose>
<xsl:when test="not($children)">
<xsl:value-of select="count($descendants)"/>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="count-descendants">
<xsl:with-param name="descendants" select="$descendants | $children"/>
<xsl:with-param name="level" select="$children"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="/">
<xsl:variable name="start-item" select="key('id', $start-id)"/>
<xsl:call-template name="count-descendants">
<xsl:with-param name="level" select="$start-item"/>
</xsl:call-template>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/3NzcBsK/0
和
https://xsltfiddle.liberty-development.net/3NzcBsK/1
和
https://xsltfiddle.liberty-development.net/3NzcBsK/2
拥有样本数据。