xsl:apply-template仅适用于具有特定属性值的节点

时间:2010-08-19 22:03:30

标签: xslt transform

我有一个XML文档,我接受了XSLT。结构类似于:

<root>
  <item value="1">
     <object/>
  </item>
  <item value="2" />
     <object/>
  </item>
</root>

我的目标是最终得到一个类似于:

的转换XML
<root>
 <parent>
  <object-one value-one="1"/>
 </parent>
 <parent>
  <object-two value-two="2"/>
 </parent>
</root>

我的XSLT类似于:

<xsl:apply-templates select="object" />


<xsl:template match="object">
    <xsl:call-template name="1" />
    <xsl:call-template name="2" />
</xsl:template>

<xsl:template name="1" match="object[item/@value = '1'">
  <xsl:element name="object-one" namespace="http://something.org">
    <xsl:attribute name="_Description">
      <xsl:value-of select="@_Type"/>
    </xsl:attribute>
    <xsl:attribute name="_Type">
      <xsl:value-of select="@_Amount"/>
   </xsl:attribute>
  </xsl:element>
</xsl:template>

 <xsl:template name="2" match="object[item/@value = '2'">
  <xsl:element name="object-two" namespace="http://something.org">
    <xsl:attribute name="OriginalAmount">
      <xsl:value-of select="@_Amount"/>
    </xsl:attribute>
  </xsl:element>
</xsl:template>

问题是所有项目节点都应用了相同的模板。如何将模板仅应用于特定节点?

2 个答案:

答案 0 :(得分:9)

编辑:现在针对不同的输入样本(针对格式正确的更正):

<root>
    <item value="1">
        <object/>
    </item>
    <item value="2" >
        <object/>
    </item>
</root>

此样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:num="number" extension-element-prefixes="num">
    <num:num>one</num:num>
    <num:num>two</num:num>
    <xsl:template match="root">
        <xsl:copy>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="item">
        <parent>
            <xsl:apply-templates/>
        </parent>
    </xsl:template>
    <xsl:template match="object">
        <xsl:variable name="vTextNumber" select="document('')/*/num:*[number(current()/../@value)]"/>
        <xsl:element name="object-{$vTextNumber}">
            <xsl:attribute name="value-{$vTextNumber}">
                <xsl:value-of select="../@value"/>
            </xsl:attribute>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

输出:

<root>
    <parent>
        <object-one value-one="1" />
    </parent>
    <parent>
        <object-two value-two="2" />
    </parent>
</root>

编辑2 :现在,样式表片段中出了什么问题?好吧,看起来你不知道处理器如何解决模板规则应用,也就是XPath navegation。

首先,此object[item/@value = '1']仅匹配此类输入

<object>
    <item value="1"/>
</object>

其次,考虑这三条规则

1 -

<xsl:template match="object">
</xsl:template> 

2 -

<xsl:template name="1" match="object[../@value = '1']"> 
</xsl:template> 

3 -

<xsl:template name="2" match="object[../@value = '2']"> 
</xsl:template> 

使用上次提供的输入,第一个object元素(按文档顺序)将匹配规则1和2,然后处理器将解析为应用规则2.为什么?来自http://www.w3.org/TR/xslt#conflict

  

接下来,所有匹配的模板规则   优先级低于匹配优先级   模板规则或规则   最高优先级被淘汰   考虑。一个优先权   模板规则由。指定   模板上的优先级属性   规则。这个价值必须是真实的   数字(正面或负面),   将生产数量与a匹配   可选的前导减号( - )。该   默认优先级计算为   如下:

     
      
  • 如果模式包含由|分隔的多个替代项,那么它   等同于一组模板规则,每个模板规则一个   替代品。
  •   
  • 如果模式的形式为QName,则前缀为
      ChildOrAttributeAxisSpecifier或具有表单处理指令(Literal)
      在ChildOrAttributeAxisSpecifier之前,优先级为0。
  •   
  • 如果模式的格式为NCName:*前面有一个
      ChildOrAttributeAxisSpecifier,则优先级为-0.25。
  •   
  • 否则,如果模式只包含NodeTest   在ChildOrAttributeAxisSpecifier之前,优先级为-0.5。
  •   
  • 否则,优先级为0.5。
  •   

答案 1 :(得分:0)

也许你可以让你的比赛更具体:

<xsl:template name="item1" match="item[@value=1]">
    <xsl:element name="item" namespace="http://something.org">
        <xsl:attribute name="_Description">
            <xsl:value-of select="@_Type"/>
        </xsl:attribute>
        <xsl:attribute name="_Type">
            <xsl:value-of select="@_Amount"/>
        </xsl:attribute>
    </xsl:element>
</xsl:template>

<xsl:template name="item2" match="item[@value=2]">
    <xsl:element name="item2_item" namespace="http://something.org">
        <xsl:attribute name="OriginalAmount">
            <xsl:value-of select="@_Amount"/>
        </xsl:attribute>
    </xsl:element>
</xsl:template>