Reputation: 37
I'm new to XPath expressions in XSLT and have hit my head against the desk for too long. I'd like to evaluate a sibling node within the first preceding ancestor of the current node and test if that node is the same.
Here's my XML:
<item>
<number>1.0</number>
<category>Data</category>
<functionality>Search Screen</functionality>
<requirement_type>SIT</requirement_type>
<table>Table</table>
</item>
<item>
<number>1.1</number>
<category>Data</category>
<functionality>Search Screen</functionality>
<requirement_type>SIT</requirement_type>
</item>
Here's my XSLT:
<xsl:for-each select="item">
<xsl:if test="not(preceding-sibling::*[position()=1])">
<xsl:value-of select="category"/>
</xsl:if>
</xsl:for-each>
Essentially, I'm trying to test whether the <category>
child node of the the second <item>
node is the same as the <category>
child node of the the first <item>
node.
Searching similar StackOverflow questions gets me close, but just not there ....
Upvotes: 0
Views: 559
Reputation: 22637
Assuming a well-formed input document that has a single outermost element. Also, as you can see, I have added an id
attribute to the item
elements to be able to tell them apart.
XML Input
<root>
<item id="1">
<number>1.0</number>
<category>Data</category>
<functionality>Search Screen</functionality>
<requirement_type>SIT</requirement_type>
<table>Table</table>
</item>
<item id="2">
<number>1.1</number>
<category>Data</category>
<functionality>Search Screen</functionality>
<requirement_type>SIT</requirement_type>
</item>
</root>
To find out whether the category
child element of the immediately preceding sibling item
element is the same, you could use
<xsl:if test="category = preceding-sibling::item[1]/category">
If the semantics should actually be different, you really need to explain this more clearly, perhaps also modifying the sample document.
XSLT Stylesheet
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" encoding="UTF-8" indent="yes" />
<xsl:template match="/root">
<result>
<xsl:for-each select="item">
<xsl:if test="category = preceding-sibling::item[1]/category">
<xsl:value-of select="@id"/>
</xsl:if>
</xsl:for-each>
</result>
</xsl:template>
</xsl:transform>
XML Output
<?xml version="1.0" encoding="UTF-8"?>
<result>2</result>
Try this transformation online here.
EDIT
Yes, I'm trying to group the items by category. Basically, I want to get a distinct group of items within one category.
For completeness, then, as Michael has noted, you are trying to solve a grouping problem. In XSLT 1.0, use a key and do Muenchian grouping. In XLST 2.0, use xsl:for-each-group
. You'll easily find examples for both techniques.
Upvotes: 1