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>
精彩评论