How to select the grandparent of a node using xslt

前端 未结 2 1528
悲&欢浪女
悲&欢浪女 2021-02-04 15:56

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:



        
相关标签:
2条回答
  • 2021-02-04 16:08

    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.

    Certainly it will not "work", because the <xsl:call-template> instruction doesn't have a select attribute!

    You may pass parameters using <xsl:with-param> children of the <xsl:call-template> instruction, like this:

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

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

    For a real grandparent:

    ../..
    

    for the closest ancestor element with name someName:

    ancestor::someName[1]
    

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

    ancestor::*[name()=$ancName][1]
    
    0 讨论(0)
  • 2021-02-04 16:19

    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.

    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"):

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

    I want to modify the album based on whether a certain label is present. Remember the general format for targeting nodes is: target-node[target-condition]. To modify any album elements that have a Capitol label grandchild element, I'd use this:

    album[*/label='Capitol']
    

    So consider this stylesheet to add a new attribute and 2 new child elements to album's 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's Lonely Hearts Club Band</title>  
      <artist>The Beatles</artist>  
      <year>1967</year>  
      <labels> 
        <label>Parlophone</label>  
        <label>Capitol</label> 
      </labels> 
      <new-element2/>
    </album>
    

    Some sandbox test resources:

    • http://www.whitebeam.org/library/guide/TechNotes/xpathtestbed.rhtm
      • To see what nodes a given XPath expression actually targets
    • http://unindented.org/projects/xslt-tester-applet/run/
      • To try out a stylesheet
    0 讨论(0)
提交回复
热议问题