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

ala*_*lan 10 xslt transform

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

<root>
  <item value="1">
     <object/>
  </item>
  <item value="2" />
     <object/>
  </item>
</root>
Run Code Online (Sandbox Code Playgroud)

我的目标是最终得到一个转换后的XML,类似于:

<root>
 <parent>
  <object-one value-one="1"/>
 </parent>
 <parent>
  <object-two value-two="2"/>
 </parent>
</root>
Run Code Online (Sandbox Code Playgroud)

我的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>
Run Code Online (Sandbox Code Playgroud)

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

小智 9

编辑:现在为不同的输入样本(校正良好形式):

<root>
    <item value="1">
        <object/>
    </item>
    <item value="2" >
        <object/>
    </item>
</root>
Run Code Online (Sandbox Code Playgroud)

这个样式表:

<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>
Run Code Online (Sandbox Code Playgroud)

输出:

<root>
    <parent>
        <object-one value-one="1" />
    </parent>
    <parent>
        <object-two value-two="2" />
    </parent>
</root>
Run Code Online (Sandbox Code Playgroud)

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

首先,这object[item/@value = '1']只会匹配这种输入

<object>
    <item value="1"/>
</object>
Run Code Online (Sandbox Code Playgroud)

其次,考虑这三条规则

1 -

<xsl:template match="object">
</xsl:template> 
Run Code Online (Sandbox Code Playgroud)

2 -

<xsl:template name="1" match="object[../@value = '1']"> 
</xsl:template> 
Run Code Online (Sandbox Code Playgroud)

3 -

<xsl:template name="2" match="object[../@value = '2']"> 
</xsl:template> 
Run Code Online (Sandbox Code Playgroud)

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

接下来,不考虑优先级高于匹配模板规则的所有匹配模板规则或具有最高优先级的规则.模板规则的优先级由模板规则的priority属性指定.此值必须是实数(正数或负数),将生产数与可选的前导减号( - )匹配.默认优先级计算如下:

  • 如果模式包含由|分隔的多个备选项,则将其
    等效地处理为一组模板规则,每个备
    选项对应一个规则.
  • 如果模式具有QName的形式,前面是
    ChildOrAttributeAxisSpecifier,或者表单处理指令(Literal)
    前面有ChildOrAttributeAxisSpecifier,则优先级为0.
  • 如果模式的格式为NCName:*,前面是
    ChildOrAttributeAxisSpecifier,则优先级为-0.25.
  • 否则,如果模式只包含一个以ChildOrAttributeAxisSpecifier开头的NodeTest,则优先级为-0.5.
  • 否则,优先级为0.5.