I'm in a situation where I can only test for the child node, but I have to apply tags to the grandparent of this child node.
I've tried using:
<xsl:call-template name="grandparent" select="parent::parent::node()"/>
and:
<xsl:call-template name="grandparent" select="ancestor::node [@nameofgrandparentnode]"/>
But neither works.
The level of the grandparent node is not fixed, so I figure I can't use [@level=#] either. Any ideas on how to select it would be greatly appreciated.
EDIT: -- This part has been posted as a new question:
xslt select grandparent node depending on an attribute value of its grandchild node
Selecting the node using the suggestions from below worked. Thanks! However I also need to test by the attribute of the grandparent or grandchild node.
I've tried:
<xsl:template name"one" match="grandparentnode">
<Tag1>
<xsl:apply-templates select="parentNode" />
</Tag1>
</xsl:template>
<xsl:template name="two" match="grandparentnode[*/*/@grandchildattr='attrValue']">
<Tag2>
<xsl:apply-templates select="parentNode" />
</Tag2>
</xsl:template>
However template "two" always gets called, and "" is always inserted. Even for grandchild nodes whose attribute value is not equal to 'attrValue'.
Am I missing something here?
Certainly it will not "work", because the
<xsl:call-template>
instruction doesn't have aselect
attribute!You may pass parameters using
<xsl:with-param>
children of the<xsl:call-template>
instruction, like this:For the
select
attribute of the<xsl:with-param>
Use:For a real grandparent:
for the closest ancestor element with name
someName
:for the closest ancestor element with name contained in the variable
$ancName
:XSLT isn't procedural programming, so you have to think about things a little differently.
If I understand correctly, you want to inject new tags (additional child elements or attributes?) into your XML, but you want to add it to an ancestor when you find a specific descendant. Your example code appears to try to target the grandparent once you come across the child. Unfortunately, this may be too late.
You may need inject the new element/attribute when engine comes across the element you want to modify (the grandparent in your case), not when it comes across the child that matches the condition (or else you'll end up adding elements or attributes to the child)
Consider this input (grandparent="album", grandchild="label"):
I want to modify the
album
based on whether a certainlabel
is present. Remember the general format for targeting nodes is:target-node[target-condition]
. To modify anyalbum
elements that have aCapitol
label grandchild element, I'd use this:So consider this stylesheet to add a new attribute and 2 new child elements to
album
's that match my condition:Output (manually formatted):
Some sandbox test resources: