1

I'm creating and styling an XML file, and I'm facing a problem when trying to give numbering to an element inside an ancestor. The equivalent code of the XML I'm working on is:

<A> <B> <C> <D>Text 1</D> <D>Text 2</D> <D>Text 3</D> </C> </B> <B> <C> <D>Text 4</D> <D>Text 5</D> </C> </B> </A> <A> <B> <C> <D>Text 6</D> <D>Text 7</D> <D>Text 8</D> </C> </B> </A> 

The numbering has to be restarted on each "A", and to do that, I'm trying to get the position of each "D" inside its "A" ancestor.

I tried with an expression like count(preceding-sibling::D)+1, but the numbering restarts on each "C" element. Also I tried with count(preceding::D)+1, but it doesn't work because it selects all the previous "D" elements of the document.

The result should be:
- Text 1 and 6 -> Position 1
- Text 2 and 7 -> Position 2
- Text 3 and 8 -> Position 3
- Text 4 -> Position 4
- Text 5 -> Position 5

How could I do to count only preceding "D" elements of each "A"?

3 Answers 3

1

If the structure is as regular as your example suggests (i.e. the Ds are always inside a C which is inside a B) then you could use something like

count(preceding-sibling::D) + count(ancestor::B/preceding-sibling::B//D) + 1 

(the number of Ds before this one in the current C, plus the total number in all the preceding Bs in the same A).

If it's not quite so regular you could use a "difference" approach instead:

count(preceding::D) - count(ancestor::A/preceding::D) + 1 

(the total number of Ds before this one anywhere in the document, minus the number that precede the current A).

Sign up to request clarification or add additional context in comments.

1 Comment

Both of them worked! :) However, I'll use the second one to avoid errors if the structure changes.
0

I think you are looking for ancestor, and not preceeding-sibling.

Comments

0

Instead of using count(), use the much simpler xsl:number...

<xsl:number from="A" level="any"/> 

Example using your XML input...

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text"/> <xsl:strip-space elements="*"/> <xsl:template match="D"> <xsl:value-of select="."/> <xsl:text> --> </xsl:text> <xsl:number from="A" level="any"/> <xsl:text>&#xA;</xsl:text> </xsl:template> </xsl:stylesheet> 

Output

Text 1 --> 1 Text 2 --> 2 Text 3 --> 3 Text 4 --> 4 Text 5 --> 5 Text 6 --> 1 Text 7 --> 2 Text 8 --> 3 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.