Reputation: 124
I'm trying to transform an XML file and trying to test if a node's grandparent has a certain name but i don't know how to get to the grandparent name. this is the example I'm working on. what i tried to do is to get the parent and then find the parent of the parent but it didn't work.
thanks.
<?xml version="1.0" encoding="UTF-8"?>
<breakfast_menu>
<food_XX>
<food_X>
<food>
<name>Belgian Waffles</name>
</food>
</food_X>
</food_XX>
<food_XX1>
<food_X>
<food>
<name>Strawberry Belgian Waffles</name>
</food>
</food_X>
</food_XX1>
</breakfast_menu>
and this is the xsl code:
<?xml version="1.0" encoding="UTF-8"?>
<html xsl:version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<body style="font-family:Arial;font-size:12pt;background-color:#EEEEEE">
<xsl:for-each select=".//food">
<xsl:variable name="parentName" select="parent::food_X" />
<xsl:value-of select="name($parentName)" />
<xsl:if test="name(parent::$parentName)='food_XX1'">
<div style="background-color:teal;color:white;padding:4px">
<span style="font-weight:bold"><xsl:value-of select="name"/> - </span>
</div>
</xsl:if>
</xsl:for-each>
</body>
</html>
Upvotes: 0
Views: 1014
Reputation: 163322
Even better, use template rules.
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body style="font-family:Arial;font-size:12pt;background-color:#EEEEEE">
<xsl:apply-templates select=".//food">
</body>
</html>
</xsl:template>
<xsl:template match="food"/>
<xsl:template match="food_XX1/*/food">
<div style="background-color:teal;color:white;padding:4px">
<span style="font-weight:bold"><xsl:value-of select="name"/> - </span>
</div>
</xsl:template>
</xsl:transform>
Upvotes: 1
Reputation: 66723
The parent::
axis selects the parent of the context node.
In your example, the context node is the food
element being processed inside the xsl:for-each
. parent::food_X
is the equivalent of ./parent::food_X
When you selected parent::food_X
, it is attempting to select an element named food_X
that is the parent of the context node (in this case, it is the food
element). Then, when attempting to select the grandparent with parent::$parentName
, was essentially saying, "give me the parent of this food
element if it is a food_X
element", rather than asking for the parent of food_X
.
In order to find the parent of the $parentName
, you need to use a step from $parentName
, so that it looks for the parent of $parentName
, and not the parent of the food
element:
<xsl:if test="name($parentName/parent::*)='food_XX1'">
You could simplify your test further. Rather than selecting any parent element and then testing it's name, select the parent element food_XXX1
:
<xsl:if test="$parentName/parent::food_XX1">
Even more simple, you could eliminate the $parentName
variable from your XSLT and just use this:
<xsl:if test="parent::food_X/parent::food_XX1">
Upvotes: 1
Reputation: 70618
To find the parent name, you can just do this...
<xsl:if test="name(../..)='food_XX1'">
And for grandparents....
<xsl:if test="name(../..)='food_XX1'">
Note that, given your current XSLT, if the intention is just to output food
nodes under food_XX1
you could re-write it as this....
<html xsl:version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<body style="font-family:Arial;font-size:12pt;background-color:#EEEEEE">
<xsl:for-each select=".//food_XX1/*/food">
<div style="background-color:teal;color:white;padding:4px">
<span style="font-weight:bold"><xsl:value-of select="name"/> - </span>
</div>
</xsl:for-each>
</body>
</html>
Upvotes: 1