XSLT - 用于获取嵌套XML节点的递归模板用法

时间:2015-09-02 07:55:20

标签: xml templates xslt recursion

我在使用XML和XSLT时遇到了问题。我想创建一个如下所示的XML文件:

<Root>
    <TopNode>
        <ChildNode>
            <!-- Some elements -->
            <ListOfChilds>
                <ChildNode/> <!-- 0 to N ChildNodes within a Childnode which can again have ChildNodes as well and so on -->
            </ListOfChilds>
            <!-- Some more elements -->
        </ChildNode>
        <ChildNode>
            ...
        </ChildNode>
    </TopNode>
<Root>

正如您所看到的,需要进行某种递归,因为每个ChildNode都可以包含多个可以包含多个ChildNode的ChildNode ......依此类推。我尝试使用<Root><TopNode><ChildNode>元素的模板来实现此目的。我的XSLT看起来像这样:

<xsl:template match="/">
    <Root>
        <xsl:apply-templates select="TopNode"/>
    </Root>
</xsl:template>

<xsl:template match="TopNode">
    <TopNode>
        <xsl:apply-templates select="ChildNode"/>
    </TopNode>
</xsl:template>

<xsl:template match="ChildNode">
    <ChildNode>
        <!-- Some elements -->
        <ListOfChilds>
            <xsl:if test="ChildNode">
                <xsl:apply-templates select="ChildNode"/>
            </xsl:if>
        </ListOfChilds>
        <!-- Some more elements -->
    </ChildNode>
</xsl:template>

但是,我在XML文件中获得的唯一输出是<Root/>。你能告诉我在转型中出了什么问题吗?理论上我是否想要这样做,或者我应该尝试一种完全不同的方法?我现在真的很丢失,任何帮助都会非常感激!谢谢!

2 个答案:

答案 0 :(得分:1)

如果您使用xsl:apply-templates(适用于子项),则XSLT会自动完成递归。如果您有这些子项的匹配模板(并且确实如此)并在其中应用模板,则会有递归。你走在正确的轨道上。

<xsl:if test="ChildNode">
    <xsl:apply-templates select="ChildNode"/>
</xsl:if>

这不是必需的。如果有ChildNode个元素,则仅应用模板有效,因此xsl:if是多余的。

从本质上讲,你使用正确的方法,但你在开始时犯了一个小错误:

<xsl:apply-templates select="TopNode"/>

此处的上下文节点是/,即根节点。但您的元素不是TopNode,而是Root。将其更改为Root/TopNode,您将看到输出。

答案 1 :(得分:0)

这是一个使用递归模板的简单示例。

此嵌套子合约的合约清单

    <contracts>                                                             
            <contract id="1">                                               
                    <supplier>koos</supplier>                               
                    <price>1000000</price>                                  
                    <subcontracts>                                          
                            <contract id="1.1">                             
                                    <supplier>piet</supplier>               
                                    <price>500000</price>                   
                            </contract>                                     
                            <contract id="1.2">                             
                                    <supplier>jan</supplier>                
                                    <price>500000</price>                   
                            </contract>                                     
                    </subcontracts>                                         
            </contract>                                                     
            <contract id="2">                                               
                    <supplier>gert</supplier>                               
                    <price>3000</price>
                    <subcontracts>
                            <contract id="2.1">
                                    <supplier>piet</supplier>
                                    <price>1000</price>
                            </contract>
                            <contract id="2.2">
                                    <supplier>jan</supplier>
                                    <price>1000</price>
                                    <subcontracts>
                                            <contract id="2.2.1">
                                                    <supplier>kleinjan</supplier>
                                                    <price>10</price>
                                            </contract>
                                    </subcontracts>
                            </contract>
                            <contract id="2.3">
                                    <supplier>awie</supplier>
                                    <price>1000</price>
                            </contract>
                    </subcontracts>
            </contract>
    </contracts>

可以使用此模板进行转换

    <?xml version="1.0"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
            <xsl:output method="text"/>
            <xsl:template match="/contracts">
                    <xsl:apply-templates select="contract"/>
            </xsl:template>
            <xsl:template match="contract">
                    <xsl:value-of select="supplier"/><xsl:text> </xsl:text><xsl:value-of select="price"/>
                    <xsl:apply-templates select="subcontracts"/>
            </xsl:template>
    </xsl:stylesheet>

生成此输出

koos 1000000
     piet 500000
     jan 500000
gert 3000
    piet 1000
    jan 1000
        kleinjan 10
    awie 1000