开发者

xsl:apply-template to only nodes with specific attribute value

开发者 https://www.devze.com 2023-01-12 03:04 出处:网络
I have an XML document which I\'m subjected to an XSLT.The structure is similar to: <root> <item value=\"1\">

I have an XML document which I'm subjected to an XSLT. The structure is similar to:

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

My goal is to end up with a transformed XML similar to:

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

My XSLT is similar to:

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

The problem is the all item nodes are having the same templ开发者_高级运维ate applied. How can I apply a template to only specific nodes?


EDIT: Now for different input sample (corrected for well-formed):

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

This stylesheet:

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

Output:

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

EDIT 2: Now, what is wrong within your stylesheet fragment? Well, it looks like you don't know how the processor resolves template rules applying, also XPath navegation.

First, this object[item/@value = '1'] will match only this kind of input

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

Second, consider this three rules

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> 

With your last provided input, first object element (in document order) will match rules 1 and 2, and then the processor would resolve to apply rule 2. Why? From http://www.w3.org/TR/xslt#conflict

Next, all matching template rules that have lower priority than the matching template rule or rules with the highest priority are eliminated from consideration. The priority of a template rule is specified by the priority attribute on the template rule. The value of this must be a real number (positive or negative), matching the production Number with an optional leading minus sign (-). The default priority is computed as follows:

  • If the pattern contains multiple alternatives separated by |, then it
    is treated equivalently to a set of template rules, one for each
    alternative.
  • If the pattern has the form of a QName preceded by a
    ChildOrAttributeAxisSpecifier or has the form processing-instruction(Literal)
    preceded by a ChildOrAttributeAxisSpecifier, then the priority is 0.
  • If the pattern has the form NCName:* preceded by a
    ChildOrAttributeAxisSpecifier, then the priority is -0.25.
  • Otherwise, if the pattern consists of just a NodeTest preceded by a ChildOrAttributeAxisSpecifier, then the priority is -0.5.
  • Otherwise, the priority is 0.5.


Perhaps you can make your matches more specific:

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

精彩评论

暂无评论...
验证码 换一张
取 消