如何使用XPath比较xsl:for-loop中的两个XML元素

时间:2012-03-20 15:18:56

标签: xml xslt xpath

我有以下问题:

在样式表文档中,我想从相对简单的xml文件创建输出。 虽然大多数常见的XPath和XSLT并不那么困难,但比较两个元素并决定,如何继续下去是一个很大的问题。

示例xml:

<root>
    <foo>
        <value>1</value>
        <name>foo1</name>
    </foo>
    <foo>
        <value>2</value>
        <name></name>
    </foo>
    <foo>
        <value>3</value>
        <name>foo3</name>
    </foo>

    <bar>
        <value>1</value>
    </bar>
    <bar>
        <value>2</value>
    </bar>
</root>
样式表中的

是一个xsl:for循环,它试图决定是否显示当前节点:

[...]
<xsl:for-each select="bar">
    <xsl:if test="//foo[value=./value]/name">
        <!-- go on, if the content of the 'name' element is not empty -->
    </xsl:if>
</xsl:for-each>
[...]

如果来自'foo'的'name'元素的内容不为空,则使用'value'元素的euqality,意图只是继续使用这些东西。 结果是,'bar'中的每一行都会创建一个输出事件,如果我打算不为第二个条目设置一个,因为'// foo [2] / name'为空。

我不确定,现在该怎么办......也许生成的密钥就足够了!?我不知道......

感谢您的每一条评论!

2 个答案:

答案 0 :(得分:1)

使用密钥,例如

<xsl:key name="k1" match="foo" use="value"/>

作为xsl:stylesheet的孩子然后

<xsl:for-each select="bar[normalize-space(key('k1', value)/name)]">...</xsl:for-each>

答案 1 :(得分:1)

您可能希望使用以下内容:

<xsl:template match="/">
    <root>
        <xsl:for-each select="//bar">
            <xsl:for-each select="//foo[value=current()/value]">
                <xsl:if test="name != ''">
                    <xsl:copy-of select="."/>
                </xsl:if>
            </xsl:for-each>
        </xsl:for-each>
    </root>
</xsl:template>

最引人注目的当然是你应该使用current()/ value而不是./value,因为current()引用了bar元素,而且。指的是循环的foo元素。

当应用于提供的输入时,这将给出

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <foo>
        <value>1</value>
        <name>foo1</name>
    </foo>
</root>