Hidden
Hidden

Reputation: 7482

XSL(T) and XPath preceding-sibling not working

I have the following 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>

And the following code works as expected:

<?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>

And returns what I expected:

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

But when I try to get the previous items using:

<?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>

I get:

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

Why are the two items above missing? It looks to me that the preceding-sibling isn't getting out of the folder. How can I resolve that?

A lot of thanks to whoever can help me - I've been stuck on it for too long :(

Upvotes: 2

Views: 3510

Answers (2)

Dimitre Novatchev
Dimitre Novatchev

Reputation: 243449

You seem to be confusing the preceding:: axis with the preceding-sibling:: axis.

What you want is:

<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>

when this transformation is applied on the provided XML document:

<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>

the wanted, correct result is produced:

      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/>

Upvotes: 3

guido
guido

Reputation: 19194

That's because you are selecting system-page elements, and One and Two containing system-page elements have no siblings. Three is first child in its containing system-page element, so it has no preceding sibling.

<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>

Upvotes: 1

Related Questions