XSLT - 与给定节点

时间:2015-09-14 10:02:14

标签: xml xslt xslt-2.0

我有一个xml如下,

<doc>
    <h1>header 1</h1>
    <p>para 1</p>
    <p>para 2</p>

    <h1>header 2</h1>
    <p>para 3</p>
    <p>para 4</p>

    <h1>header 3</h1>
    <p>para 5</p>
    <p>para 6</p>
</doc>

我的要求是从<h1>创建无序列表,并将这些列表项链接到<p>个节点之后。

所以期望的输出应该是,

<doc>
    <div name="list">
        <ul>
            <li><a href="h1-1">header 1</a></li>
            <li><a href="h1-2">header 2</a></li>
            <li><a href="h1-3">header 3</a></li>
        </ul>
    </div>
    <div class="content">
        <div id="h1-1">
            <p>para 1</p>
            <p>para 2</p>
        </div>
        <div id="h1-2">
            <p>para 3</p>
            <p>para 4</p>
        </div>
        <div id="h1-3">
            <p>para 5</p>
            <p>para 6</p>
        </div>
    </div>
</doc>

我写了以下xsl来完成这项任务,

       <doc>
            <div name="list">
                <ul>
                <xsl:for-each-group select="*" group-starting-with="h1">                    
                    <li><a href="h1-{count(preceding::h1)+1}"><xsl:apply-templates/></a></li>                   
                </xsl:for-each-group>
                </ul>
            </div>

            <div class="content">
                <xsl:for-each select="h1">
                    <div id="h1-{count(preceding::h1)+1}">
                        <!-- should copy follwing <p> nodes in <h1> -->
                    </div>
                </xsl:for-each>
            </div>
        </doc>

我无法解决的问题是如何将<p>节点作为以下兄弟节点复制到<h1>但在显示另一个<h1>之前。 (例子会给出清晰的想法。)

有人能建议我解决这个问题吗?

1 个答案:

答案 0 :(得分:2)

你的方法需要逆转:第一个div不需要分组,第二个需要分组。

并且没有必要考虑跟随(或之前)兄弟姐妹;只需将组缩小到p个元素。

XSLT 2.0

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="UTF-8" indent="yes"/>

<xsl:template match="doc">
    <doc>
        <div name="list">
            <ul>
                <xsl:for-each select="h1">
                    <li>
                        <a href="h1-{position()}">
                            <xsl:value-of select="."/>
                        </a>
                    </li>
                </xsl:for-each>
            </ul>
        </div>
        <div class="content">
            <xsl:for-each-group select="*" group-starting-with="h1">  
                <div id="h1-{position()}">
                    <xsl:copy-of select="current-group()[self::p]"/>
                </div>
            </xsl:for-each-group>                
        </div>
    </doc>
</xsl:template>

</xsl:stylesheet>