XSL:使用多个模板影响相同的节点

时间:2011-10-28 09:11:23

标签: xml templates xslt

据我了解,通常在XSL中,每个节点可能只受一个模板的影响。一旦节点受到模板的影响,它 - 以及 - 至关重要的是它的子/后代 - 不会受到任何其他模板的影响。

但是,有时您希望使用一个模板影响外部节点,然后使用另一个模板影响其子/后代。以下是一个可取的方法吗?其目的是将属性'attr'添加到每个节点。

源XML:     <根>         <子>             <孙子>                 < greatgrandchild>你好!             < /孙子>         < /儿童>     < /根>

XSL:     

    <xsl:template match='node()'>
        <xsl:copy>
            <xsl:apply-templates select="node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match='child'>
        <child>
            <xsl:attribute name='attr'>val</xsl:attribute>
            <xsl:apply-templates select='./*' />
        </child>
    </xsl:template>

    <xsl:template match='greatgrandchild'>
        <greatgrandchild>
            <xsl:attribute name='attr'>val</xsl:attribute>
            <xsl:value-of select='.' />
        </greatgrandchild>
    </xsl:template>

</xsl:stylesheet>

我是否在正确的位置?

提前致谢。

2 个答案:

答案 0 :(得分:0)

坦率地说,是否处理节点完全取决于您的模板和内置模板(可以覆盖)。如果foo元素节点的模板确实<xsl:apply-templates/>,则处理子节点,如果它<xsl:apply-templates select="ancestor::*"/>,则处理其祖先元素,只是给出两个示例。当然,如果您为某个不使用apply-templates进行进一步处理的元素编写模板,则处理将停止。

对于您的示例,如果要向所有元素节点添加属性,那么您需要的只是

<xsl:template match="@* | node()">
  <xsl:copy>
    <xsl:apply-templates select="@* | node()"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="*">
  <xsl:copy>
   <xsl:apply-templates select="@*"/>
   <xsl:attribute name="attr">val</xsl:attribute>
   <xsl:apply-templates/>
  </xsl:copy>
</xsl:template>

标识转换模板加一个元素节点添加新属性。

答案 1 :(得分:0)

  

据我了解,通常在XSL中,每个节点可能只受一个节点的影响   模板。一旦节点受到模板的影响,   它 - 而且,至关重要的是,它的子女/后代 - 不会受到影响   进一步的任何其他模板。

这些陈述都不是真的。可以选择不同的模板在同一节点上执行 - 这一切都取决于导致选择特定模板以执行的<xsl:apply-templates>指令。模板的应用和选择方式具有很大的灵活性,例如导入优先级,优先级,模式,......等。

甚至可以将模板制作成双节点(用作节点),就像在FXSL中一样。

  

但是,有时候,您希望使用一个模板影响外部节点,   然后使用另一个模板影响其子/后代。会的吗?   以下是一个可取的方法吗?它的目的是增加   将'attr'属性赋予每个节点。

使用最基本的XSLT设计模式 - 覆盖identity rule ,可以轻松实现这一点:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="node()|@*">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="*">
  <xsl:variable name="val" select="count(ancestor::node())"/>
  <xsl:copy>
    <xsl:attribute name="depth">
      <xsl:value-of select="$val"/>
    </xsl:attribute>
      <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

将此转换应用于提供的XML文档(更正为格式正确):

<root>
    <child>
        <grandchild>
            <greatgrandchild>hello! </greatgrandchild>
        </grandchild>
    </child>
</root>

它复制每个节点并为每个元素添加depth属性。新添加的属性的值是元素的“深度”

<root depth="1">
   <child depth="2">
      <grandchild depth="3">
         <greatgrandchild depth="4">hello! </greatgrandchild>
      </grandchild>
   </child>
</root>