XSL 1.0 中的不同值 [英] Distinct-values in XSL 1.0 inside of for each

查看:22
本文介绍了XSL 1.0 中的不同值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在 for 循环内或某个组内获取不同的值.由于 xsl:key 只能在顶层声明,我如何才能为每个组创建一个 xsl:key?在下面的示例中,组将是最外层的水果标签.请注意,还有一个 xsl:sort.如果有一种方法可以仅通过 xpaths(前同级)来完成此操作,我也很想知道此解决方案.我不确定是否需要使用 Muenchian 方法来完成此操作,但这就是我所拥有的:

I would like to get the distinct values inside of a for loop, or within some group. Since the xsl:key can only be declared at the top level, how would I be able to make a xsl:key for each group? In the example below, the group would be the most outer fruit tags. Note that there's also a xsl:sort. If there is a way to accomplish this by just xpaths (preceding-sibling), I would love to know this solution as well. I'm not sure if I would need to use the Muenchian method to accomplish this, but this is what I have:

输入.xml

<root>
<fruits>
    <fruit>
        <fruit id="2">
            <banana><taste>Yummy</taste></banana>
            <banana><taste>Disgusting</taste></banana>
        </fruit>
        <fruit id="1">
            <banana><taste>Eh</taste></banana>
            <banana><taste>Disgusting</taste></banana>
        </fruit>
    </fruit>
    <fruit>
        <fruit id="2">
            <banana><taste>Yummy</taste></banana>
            <banana><taste>Disgusting</taste></banana>
        </fruit>
        <fruit id="1">
            <banana><taste>Amazing</taste></banana>
            <banana><taste>Disgusting</taste></banana>
        </fruit>
    </fruit>    
</fruits>
</root>

转换.xsl

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:key name="taste" use="." match="taste" />
    <xsl:template match="root">
    <xsl:apply-templates select="fruits" />
    </xsl:template>
    <xsl:template match="fruits">
        <xsl:element name="newFruits">
            <xsl:call-template name="test" />
        </xsl:element>
    </xsl:template>
    <xsl:template name="test">
        <xsl:for-each select="fruit">
        <xsl:sort select="fruit/@id" />
        <xsl:element name="newFruit">
            <!-- xsl:for-each select="fruit/banana/taste[not(.=preceding::taste)]/.." /> -->
            <xsl:for-each select="fruit/banana/taste[generate-id() = generate-id(key('taste',.)[1])]/..">
                <xsl:element name="fruit">
                    <xsl:value-of select="."/>
                </xsl:element>
            </xsl:for-each>
        </xsl:element>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

输出(输出中的注释是应该出现的所需标签)

Output (comments in the output is the desired tags that should appear)

<?xml version="1.0" encoding="UTF-8"?>
<newFruits>
    <newFruit>
        <fruit>Yummy</fruit>
        <fruit>Disgusting</fruit>
        <fruit>Eh</fruit>
    </newFruit>
    <newFruit>
        <!-- <fruit>Yummy</fruit> -->
        <!-- <fruit>Disgusting</fruit> -->
        <fruit>Amazing</fruit>
    </newFruit>
</newFruits>

推荐答案

问题是您希望每个顶级 fruit 元素的 taste 元素都不同.您当前的分组正在获取整个文档的不同元素.

The issue is that you want your taste elements to be distinct per each top-level fruit element. Your current grouping is getting the distinct elements for the whole document.

如果您无法更新到 XSLT 2.0,那么您必须在 XSLT 1.0 中使用连接键来包含相关 fruit 元素的唯一标识符,这可以通过使用 generate-id()

If you can't update to XSLT 2.0 then shed a tear, as you have to then use a concatenated key in XSLT 1.0, to include a unique identifier for the relevant fruit element, which can be achieved by using generate-id()

 <xsl:key name="taste" use="concat(generate-id(../../..), '|', .)" match="taste" />

然后,在您的测试"模板中,定义一个变量来保存相关水果的 id...

Then, in your "test" template, define a variable to hold the id for the relevant fruit...

 <xsl:variable name="id" select="generate-id()" />

而你获得独特品味的表达变成了这样......

And your expression to get the distinct tastes becomes this...

<xsl:for-each select="fruit/banana/taste[generate-id() = generate-id(key('taste', concat($id, '|', .))[1])]">

试试这个 XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
    <xsl:output method="xml" indent="yes" />

    <xsl:key name="taste" use="concat(generate-id(../../..), '|', .)" match="taste" />

    <xsl:template match="root">
        <xsl:apply-templates select="fruits" />
    </xsl:template>

    <xsl:template match="fruits">
        <newFruits>
            <xsl:call-template name="test" />
        </newFruits>
    </xsl:template>

    <xsl:template name="test">
        <xsl:for-each select="fruit">
            <xsl:variable name="id" select="generate-id()" />
            <newFruit>
                <!-- xsl:for-each select="fruit/banana/taste[not(.=preceding::taste)]/.." /> -->
                <xsl:for-each select="fruit/banana/taste[generate-id() = generate-id(key('taste', concat($id, '|', .))[1])]">
                    <fruit>
                        <xsl:value-of select="."/>
                    </fruit>
                </xsl:for-each>
            </newFruit>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

注意,你并不是真的需要第一个模板,我也看不到命名模板的意义,所以你可以把上面的XSLT简化成这样...

Note, you don't really need the first template, and I can't see the point of a named template, so you can simplify the above XSLT to this...

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
    <xsl:output method="xml" indent="yes" />

    <xsl:key name="taste" use="concat(generate-id(../../..), '|', .)" match="taste" />

    <xsl:template match="fruits">
        <newFruits>
            <xsl:apply-templates select="fruit" />
        </newFruits>
    </xsl:template>

    <xsl:template match="fruit">
        <xsl:variable name="id" select="generate-id()" />
        <newFruit>
            <!-- xsl:for-each select="fruit/banana/taste[not(.=preceding::taste)]/.." /> -->
            <xsl:for-each select="fruit/banana/taste[generate-id() = generate-id(key('taste', concat($id, '|', .))[1])]">
                <fruit>
                    <xsl:value-of select="."/>
                </fruit>
            </xsl:for-each>
        </newFruit>
    </xsl:template>
</xsl:stylesheet>

这篇关于XSL 1.0 中的不同值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆