我有一个XML输入文档:
<root>
<MultiItem name="m1">
<MultiItem name="m2">
<SingleItemA name="s1A" >
<SingleItemB name="s1B"/>
</SingleItemA >
<SingleItemB name="s2B" />
</MultiItem>
<SingleItemB name="s3B" />
<MultiItem name="m3">
<SingleItemA name="s2A" >
<MultiItem name ="m4">
<SingleItemA name="s3A"/>
</MultiItem>
</SingleItemA>
<MultiItem name="m5">
<SingleItemB name="s4B" />
<SingleItemA name="s4A" >
<SingleItemA name="s5A" />
</SingleItemA>
</MultiItem>
</MultiItem>
</MultiItem>
</root>
这包含<MultiItem>
个节点,这些节点可以包含任意数量的<SingleItemA>
,<SingleItemB>
或<MultiItem>
节点。还有<SingleItem>
个仅包含一个节点的节点。
嵌套<MultiItem>
节点的数量也没有限制,因此可能会发生以下情况:
<MultiItem>
<MultiItem>
<MultiItem>
<MultiItem>
<MultiItem>
<MultiItem>
<SingleItemA />
</MultiItem>
</MultiItem>
</MultiItem>
</MultiItem>
</MultiItem>
</MultiItem>
我需要编写一个xslt模板,该模板递归地遍历所有元素,同时计算<SingleItemA>
节点的数量。基于此计数,将应用其他模板。这都是更大的XSLT转换的一部分,因此apply-templates
调用将无法工作。
我也只关心<MultiItem>
节点中的第一级元素。如果一个<SingleItemA>
节点位于另一个<SingleItemA>
节点内,则我不希望它计算在内。但是,如果一个<MultiItem>
节点位于另一个<MultiItem>
节点内,则需要检查其中的<SingleItemA>
个节点。对于上面的示例,由于<SingleItemA>
个节点的名称为s1A,s2A,s4A
这是我到目前为止提出的模板,它是从与<MultiItem>
之类的xsl:call template name='GetCountAndAppy.>
匹配的模板中调用的,其参数计数等于零:
<xsl:template name="GetCountAndApply">
<xsl:param name="count"/>
<xsl:for-each select="child::*">
<xsl:choose>
<xsl:when test="name() = 'MultiItem'">
<xsl:for-each select="./*">
<xsl:call-template name="GetCountAndApply">
<xsl:with-param name="count" select="$count"/>
</xsl:call-template>
</xsl:for-each>
</xsl:when>
<xsl:when test="name() = 'SingleItemA'">
<xsl:call-template name="GetCountAndApply">
<xsl:with-param name="count" select="$count + 1"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise/> <!-- skip to next child -->
</xsl:choose>
</xsl:for-each>
<xsl:if test="'HasLoopedThroughEverything[NEED A WAY TO TELL]'">
<xsl:choose>
<xsl:when test="$count > 1">
<!--Apply templates-->
</xsl:when>
<xsl:otherwise>
<!--Apply different templates-->
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
我一直无法弄清楚是否要放入if循环中来说明没有其他可循环的情况。是否有人对如何执行此操作有任何建议,或者我在思考过程中哪里出了错。 XSLT对我来说还很新。
答案 0 :(得分:1)
您实际上仍然不需要递归模板。尽管可能有更好的方法(特别是如果您可以使用XSLT 3.0),则可以尝试执行以下操作:
<xsl:variable name="ancestorCount" select="count(ancestor::SingleItemA)" />
<xsl:variable name="count" select="count(.//SingleItemA[count(ancestor::SingleItemA) = $ancestorCount])" />