xsl:number in child node
I have XML which looks like this:
<A></A>
<A></A>
<A>
<a/>
<a/>
</A>
As you can see it has two levels <A>
and <a>
.
I wrote XSL tranform that generates index number on every <A>
element and it works:
<xsl:template match "A">
<xsl:element name="Person">
<xsl:attribute name="id">
<xsl:number count="A"/>
</xsl:attribute>
</xsl:element>
</xsl>
Output:
<Person id="1"/>
<Person id="2"/>
<Person id="3"/>
But how to write xsl:number to generate the same number at <a>
level (at ???
)?
<xsl:template match "A">
<xsl:element name="Person">
<xsl:attribute name="id">
<xsl:number count="A"/>
<xsl:apply-templates select="a"/>
</xsl:attribute>
&l开发者_高级运维t;/xsl:element>
</xsl>
<xsl:template match "a">
<xsl:element name="Item">
<xsl:attribute name="id">
<xsl:number count="???"/>
</xsl:attribute>
</xsl:element>
</xsl>
Expected output (I want the same id
for <Person>
and <Item>
):
<Person id="1"/>
<Person id="2"/>
<Person id="3">
<Item id="3"/>
<Item id="3"/>
</Person>
I know this must be some simple XPATH expression, but I really got stucked on this.
You could simply pass the computed number down if you really want the same:
<xsl:template match="A">
<xsl:variable name="id">
<xsl:number count="A"/>
</xsl:variable>
<Person id="{$id}">
<xsl:apply-templates select="a">
<xsl:with-param name="pid" select="$id"/>
</xsl:apply-templates>
</Person>
</xsl:template>
<xsl:template match="a">
<xsl:param name="pid"/>
<Item id="{$pid}"/>
</xsl:template>
In response to your request to do it without passing a variable, see below.
The drawback is that <xsl:number>
can't be used directly in an Attribute Value Template (as @Martin used the $id
variable), so generating the id
attribute becomes verbose.
<xsl:template match="A">
<Person>
<xsl:attribute name="id">
<xsl:number count="A" />
</xsl:attribute>
<xsl:apply-templates select="a" />
</Person>
</xsl:template>
<xsl:template match="a">
<Item>
<xsl:attribute name="id"> <!-- I would name it personRef or something -->
<xsl:number count="A" />
</xsl:attribute>
</Item>
</xsl:template>
(Untested.)
The key here is using select=".."
on xsl:number
in the "a"
template. Edit: It turns out that the select=".."
is not actually necessary. Since the context node a
does not match the count pattern A
, it starts from the nearest ancestor that does match it. What a web of useful defaults this instruction has!
OK, I have the answer. However I marked Lars' answer as the solution.
<xsl:template match "A">
<xsl:element name="Person">
<xsl:attribute name="id">
<xsl:number count="A"/>
<xsl:apply-templates select="a"/>
</xsl:attribute>
</xsl:element>
</xsl>
<xsl:template match "a">
<xsl:element name="Item">
<xsl:attribute name="id">
<xsl:number count="A" level="any"/>
</xsl:attribute>
</xsl:element>
</xsl>
It was enough to add level="any"
attribute.
精彩评论