XSL (T) и 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   2  

2 ответа:

Вы, кажется, путаете ось 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/>

Это потому, что вы выбираете system-page элементы, а One и Two содержащие 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>