XSL(T)和XPath previous-sibling无法正常工作

时间:2012-02-28 00:12:58

标签: xslt xpath

我有以下XML:

<system-folder>
    <system-folder>
        <system-page>
            <display-name>One</display-name>
        </system-page>
    </system-folder>
    <system-folder>
        <system-page>
            <display-name>Two</display-name>
        </system-page>
    </system-folder>
    <system-folder current="true">
        <system-page>
            <display-name>Three</display-name>
        </system-page>
        <system-page>
            <display-name>Four</display-name>
        </system-page>
        <system-page>
            <display-name>Five</display-name>
        </system-page>
    </system-folder>
</system-folder>

以下代码按预期工作:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template match="/">
        <xsl:for-each select="//system-folder[@current="true"]/..//system-page">
            Current: <xsl:value-of select="display-name"/><br/>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

并返回我的预期:

Current: One
Current: Two
Current: Three
Current: Four
Current: Five

但是当我尝试使用以下项目获取以前的项目时:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template match="/">
       <xsl:for-each select="//system-folder[@current="true"]/..//system-page">
           Previous: <xsl:value-of select="preceding-sibling::*[1]/display-name"/><br/>
           Current: <xsl:value-of select="display-name"/><br/><br/>
       </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

我明白了:

Previous: 
Current: One

Previous: <-- Why is this missing?
Current: Two

Previous: <-- Why is this missing?
Current: Three

Previous: Three
Current: Four

Previous: Four
Current: Five

为什么上面的两件物品丢失了?在我看来,前面的兄弟没有离开文件夹。我该如何解决?

非常感谢能帮助我的人 - 我已经坚持了很长时间:(

2 个答案:

答案 0 :(得分:3)

您似乎将preceding::轴与preceding-sibling::轴混淆。

你想要的是

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <xsl:for-each select=
        "//system-folder[@current='true']/..//system-page">
          Previous: <xsl:value-of select=
          "preceding::system-page[1]/display-name"/>
            <br/>
            Current: <xsl:value-of select="display-name"/>
            <br/>
            <br/>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

将此转换应用于提供的XML文档

<system-folder>
    <system-folder>
        <system-page>
            <display-name>One</display-name>
        </system-page>
    </system-folder>
    <system-folder>
        <system-page>
            <display-name>Two</display-name>
        </system-page>
    </system-folder>
    <system-folder current="true">
        <system-page>
            <display-name>Three</display-name>
        </system-page>
        <system-page>
            <display-name>Four</display-name>
        </system-page>
        <system-page>
            <display-name>Five</display-name>
        </system-page>
    </system-folder>
</system-folder>

产生了想要的正确结果

      Previous: <br/>
        Current: One<br/><br/>
      Previous: One<br/>
        Current: Two<br/><br/>
      Previous: Two<br/>
        Current: Three<br/><br/>
      Previous: Three<br/>
        Current: Four<br/><br/>
      Previous: Four<br/>
        Current: Five<br/><br/>

答案 1 :(得分:1)

这是因为您选择的是system-page元素,而OneTwo元素包含的system-page元素没有兄弟姐妹。 Three是包含system-page元素的第一个子元素,因此它没有先前的兄弟。

<system-folder>
    <system-folder>
        <system-page>
            <display-name>One</display-name> 
            <!-- One's system-page is unique in this system-folder -->
        </system-page>
    </system-folder>
    <!-- same for Two -->
    <system-folder current="true">
        <system-page>
            <display-name>Three</display-name>
        </system-page>
        <system-page>
            <display-name>Four</display-name> 
            <!-- Three's system-page is sibling of this system-page 
                 in this system-folder -->
        </system-page>
    </system-folder>
</system-folder>