如何使用xslt选择节点的祖父节点

时间:2010-09-09 00:38:26

标签: xslt select xpath

我遇到的情况是我只能测试子节点,但我必须将标签应用于此子节点的祖父节点。

我尝试过使用:

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

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

但两者都不起作用。

祖父节点的级别不固定,所以我想我也不能使用[@ level =#]。关于如何选择它的任何想法将不胜感激。

编辑: - 此部分已作为新问题发布:

xslt select grandparent node depending on an attribute value of its grandchild node

使用以下建议选择节点。谢谢!但是我还需要通过祖父母或孙子节点的属性进行测试。

我试过了:

<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>

但是总是调用模板“two”,并且总是插入“”。即使是属性值不等于'attrValue'的孙子节点。

我在这里错过了什么吗?

2 个答案:

答案 0 :(得分:17)

  

我尝试过使用:

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

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

但两者都不起作用。

当然它不会“正常”,因为<xsl:call-template>指令没有select属性!

您可以使用<xsl:with-param>指令的<xsl:call-template>子项传递参数,如下所示:

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

对于select使用<xsl:with-param>属性:

对于一个真正的祖父母:

../..

表示名称为someName的最近祖先元素:

ancestor::someName[1]

表示变量$ancName中包含名称的最近祖先元素:

ancestor::*[name()=$ancName][1]

答案 1 :(得分:4)

  

我遇到的情况是我只能测试子节点,但是我必须将标签应用于这个子节点的祖父节点。

XSLT不是程序编程,所以你必须以不同的方式思考问题。

如果我理解正确,您希望将新标记(其他子元素或属性?)注入XML,但是当您找到特定的后代时,您希望将其添加到祖先。一旦遇到孩子,您的示例代码似乎会尝试以祖父母为目标。不幸的是,这可能为时已晚。

当引擎遇到您要修改的元素(在您的情况下为祖父母)时,您可能需要注入新元素/属性,而不是在遇到符合条件的子项时(或者其他)你最终会向孩子添加元素或属性)

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>

我想根据某个album是否存在来修改label。请记住,定位节点的一般格式为:target-node[target-condition]。要修改具有album标签孙元素的任何Capitol元素,我会使用它:

album[*/label='Capitol']

因此,请考虑将此样式表添加到符合我条件的album的新属性和2个新子元素:

<?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>

输出(手动格式化):

<?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>

一些沙盒测试资源: