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