开发者

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.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜