需要基于元素嵌套的序列号

时间:2014-12-10 18:44:42

标签: xslt xslt-2.0

需要基于元素嵌套的序列号。在下面的示例中,所有不是任何引用元素的子元素的引用元素都将具有序列号,任何嵌套的引用元素都应具有父序列号+小数+当前引用元素的位置。

Input.xml中

    <root>
        <front>
            <reference1 type="ref" href="a.xml">
                <reference1 type="ref" href="x.xml"/>
                <reference1 type="ref" href="z.xml"/>
            </reference>
        </front>
        <reference2 type="ref" href="b.xml"/>
        <reference2 type="ref" href="c.xml">
            <reference2 type="ref" href="d.xml">
                <reference2 type="ref" href="y.xml"/>
            </reference>
        </reference>
        <back>
            <reference3 type="ref" href="e.xml"/>
        </back>
    </root>

的Output.xml

    <root>
        <reference href="a.xml" sequence="1"/>
        <reference href="x.xml" sequence="1.1"/>
        <reference href="z.xml" sequence="1.2"/>
        <reference href="b.xml" sequence="2"/>
        <reference href="c.xml" sequence="3"/>
        <reference href="d.xml" sequence="3.1"/>
        <reference href="y.xml" sequence="3.1.1"/>
        <reference href="e.xml" sequence="4"/>
    </root>

我正在尝试这个但却无法得到逻辑:

          <xsl:template match="/">
             <root>
                 <xsl:for-each select="//reference">
                     <reference>
                                 <xsl:attribute name="href">
                                     <xsl:value-of select="@href"/>
                                 </xsl:attribute>
                         <xsl:if test="not(child::reference)">
                                 <xsl:attribute name="sequence">
                                     <xsl:value-of select="position()"/>
                                 </xsl:attribute>
                         </xsl:if>
                         <xsl:if test="child::reference">
                             <!-- something to be done here -->
                         </xsl:if>
                     </reference>    
                 </xsl:for-each>
             </root>

由于

1 个答案:

答案 0 :(得分:1)

我的建议是使用<xsl:number level="multiple"/>为你计算。我认为,为了使计数正确,您必须将其缩小到仅reference个元素。我可能错了,可能有一种更简单的方法,但我只有几分钟的时间花在这上面。

在我的示例中,我使用模式模板并将清理后的结果分配给变量。然后我将模板应用于该变量以进行实际转换。

这只适用于XSLT 2.0,但由于你标记了问题2.0,你应该没问题。

XML输入(添加了几个<foo/>元素进行测试)

<root>
    <front>
        <reference href="a.xml">
            <reference href="x.xml"/>
            <reference href="z.xml"/>
        </reference>
    </front>
    <reference href="b.xml"/>
    <foo/>
    <reference href="c.xml">
        <reference href="d.xml">
            <foo>
                <reference href="y.xml"/>                
            </foo>
        </reference>
    </reference>
    <back>
        <reference href="e.xml"/>
    </back>
</root>

XSLT 2.0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:variable name="refs">
        <refs>
            <xsl:apply-templates select="/*//reference[not(ancestor::reference)]" mode="clean"/>                
        </refs>
    </xsl:variable>

    <xsl:template match="/root">
        <xsl:copy>
            <xsl:apply-templates select="$refs"/>            
        </xsl:copy>
    </xsl:template>

    <xsl:template match="reference">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:attribute name="x">
                <xsl:number level="multiple"/>
            </xsl:attribute>
        </xsl:copy>
        <xsl:apply-templates/>
    </xsl:template>

    <xsl:template match="reference" mode="clean">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates select=".//reference[ancestor::reference[1] is current()]" mode="clean"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

XML输出

<root>
   <reference href="a.xml" x="1"/>
   <reference href="x.xml" x="1.1"/>
   <reference href="z.xml" x="1.2"/>
   <reference href="b.xml" x="2"/>
   <reference href="c.xml" x="3"/>
   <reference href="d.xml" x="3.1"/>
   <reference href="y.xml" x="3.1.1"/>
   <reference href="e.xml" x="4"/>
</root>

修改

这是问题中更新输入的更新样式表。我只需要将reference更改为*[@type='ref']并将count属性添加到xsl:number

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:variable name="refs">
        <refs>
            <xsl:apply-templates select="/*//*[@type='ref'][not(ancestor::*[@type='ref'])]" mode="clean"/>                
        </refs>
    </xsl:variable>

    <xsl:template match="/root">
        <xsl:copy>
            <xsl:apply-templates select="$refs"/>            
        </xsl:copy>
    </xsl:template>

    <xsl:template match="*[@type='ref']">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:attribute name="x">
                <xsl:number count="*[@type='ref']" level="multiple"/>
            </xsl:attribute>
        </xsl:copy>
        <xsl:apply-templates/>
    </xsl:template>

    <xsl:template match="*[@type='ref']" mode="clean">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates select=".//*[@type='ref'][ancestor::*[@type='ref'][1] is current()]" mode="clean"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>