How to select grandparent from node using xslt

I am in a situation where I can only check for a child node, but I need to apply tags to the grandparent of this child node.

I tried using:

<xsl:call-template name="grandparent" select="parent::parent::node()"/> 

and

 <xsl:call-template name="grandparent" select="ancestor::node [@nameofgrandparentnode]"/> 

But does not work.

The grandparent node level is not fixed, so I suppose I cannot use [@level = #]. Any ideas on how to choose it would be greatly appreciated.

EDIT: - This part has been published as a new question:

xslt select grandparent node depending on the attribute value of its grandson node

Choosing a node using the recommendations below. Thank you However, I also need to check the attribute of the grandfather or grandson of node.

I 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, the "two" template is always called, and "always inserted. Even for grandchild nodes whose attribute value is not equal to" attrValue ".

Did I miss something?

+7
select xpath xslt
source share
2 answers

I tried using:

 <xsl:call-template name="grandparent" select="parent::parent::node()"/> 

and

 <xsl:call-template name="grandparent" select="ancestor::node[@nameofgrandparentnode]"/> 

But does not work.

Of course, this will not work, because the <xsl:call-template> command does not have a select attribute!

You can pass parameters using the <xsl:with-param> children of the <xsl:call-template> command, for example:

 <xsl:call-template name="compute"> <xsl:param name="pAncestor" select="someExpression"/> </xsl:call-template> 

For the attribute select <xsl:with-param> Use :

For real grandparents:

 ../.. 

for the closest ancestor element named someName :

 ancestor::someName[1] 

for the closest ancestor element with the name contained in the variable $ancName :

 ancestor::*[name()=$ancName][1] 
+17
source share

I am in a situation where I can only check for a child node, but I need to apply tags to the grandparent of this child node.

XSLT is not procedural programming, so you need to think about things a little differently.

If I understand correctly, you want to add new tags to your XML (additional child elements or attributes?), But you want to add them to the ancestor when you find a specific descendant. Your sample code is trying to target grandfather when you encounter a child. Unfortunately, this may be too late.

You may need to introduce a new element / attribute when the engine encounters the element you want to change (grandfather in your case), and not when it meets a child that meets the condition (or you will end up adding elements or attributes to the child)

Consider this entry (grandparent = "album", grandchild = "label"):

 <?xml version="1.0" encoding="UTF-8"?> <album> <title>Sgt. Pepper Lonely Hearts Club Band</title> <artist>The Beatles</artist> <year>1967</year> <labels> <label>Parlophone</label> <label>Capitol</label> </labels> </album> 

I want to change the album based on the presence of a specific label . Remember that the general format for targeting nodes is: target-node[target-condition] . To change any album elements that have a Capitol label poem element, I would use the following:

 album[*/label='Capitol'] 

Therefore, consider this stylesheet to add a new attribute and 2 new children to the album that match my condition:

 <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="album[*/label='Capitol']"> <xsl:copy> <xsl:apply-templates select="@*"/> <xsl:attribute name="new-attribute">A Capitol Record</xsl:attribute> <new-element1/> <xsl:apply-templates select="node()"/> <new-element2/> </xsl:copy> </xsl:template> </xsl:stylesheet> 

Output (manually formatted):

 <?xml version="1.0" encoding="UTF-8"?> <album new-attribute="A Capitol Record"> <new-element1/> <title>Sgt. Pepper Lonely Hearts Club Band</title> <artist>The Beatles</artist> <year>1967</year> <labels> <label>Parlophone</label> <label>Capitol</label> </labels> <new-element2/> </album> 

Some resources of the test environment:

+4
source share

All Articles