使用XSL-T 1.0,如何为重复节点生成不同的输出?

时间:2018-02-06 07:28:44

标签: xml xslt

我使用客户端XSL-T从XML文档生成索引。索引如下所示:

<index>
    <topic name="A">
        <page no="127"/>
    </topic>
    <topic name="B">
        <page no="126"/>
    </topic>
    <topic name="C">
        <page no="125"/>
        <page no="128"/>
    </topic>
</index>

XSL-T模板如下所示:

<xsl:template match="/index">
    <table>
        <xsl:for-each select="topic/page">
            <xsl:sort select="@no"/>
            <tr>
                <td><xsl:value-of select="@no"/></td>
                <td><xsl:value-of select="../@name"/></td>
            </tr>
        </xsl:for-each>
    </table>
</xsl:template>

这会对页面编号<index>进行排序,并为每个页面和主题显示一个表格行。但是,我发现有时我的输入有重复的页面:

<index>
    <topic name="A">
        <page no="126"/>
    </topic>
    <topic name="B">
        <page no="126"/>
    </topic>
</index>

在这种情况下,我仍然希望为每个重复的主题和页面输出一行,但我想在页码旁边打印一个数字,表示它是第二次出现。我希望我的输出看起来像这样:

<table>
    <tr>
        <td>126</td>
        <td>Topic A</td>
    </tr>
    <tr>
        <td>126 (1)</td>
        <td>Topic B</td>
    </tr>
</table>

不幸的是,我无法确定第二次出现页码的方式。我不能使用preceding-sibling因为它给了我前面的输入兄弟,它没有排序。有没有办法做到这一点?

1 个答案:

答案 0 :(得分:2)

这听起来像是一个分组问题,您可以在XSLT 1中使用密钥和Muenchian分组来解决http://www.jenitennison.com/xslt/grouping/muenchian.html

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

<xsl:output method="html" indent="yes" doctype-system="about:legacy-compat"/>

<xsl:key name="dup" match="page" use="@no"/>

<xsl:template match="/index">
    <table>
        <xsl:for-each select="topic/page[generate-id() = generate-id(key('dup', @no)[1])]">
            <xsl:sort select="@no"/>
            <xsl:for-each select="key('dup', @no)">
                <tr>
                    <td>
                        <xsl:value-of select="@no"/>
                        <xsl:if test="position() > 1">
                            <xsl:value-of select="concat(' (', position(), ') ')"/>
                        </xsl:if>
                    </td>
                    <td><xsl:value-of select="../@name"/></td>
                </tr>                
            </xsl:for-each>

        </xsl:for-each>
    </table>
</xsl:template>


</xsl:stylesheet>

http://xsltfiddle.liberty-development.net/948Fn5g

相关问题