Reputation: 815
The following is an example of a text marked-up in XML. It contains the segments <id>
, <ad>
, and <od>
. I am trying to cycle through each document/p
to append <sum>incremented_letter</sum>
after each <id>
, <ad>
, and <od>
. The letters start over from 'a' with each <document>
. While I am successfully creating the segments and incrementing the letters using xsl:number
, the new segments are being appended at the end of p
. I'm failing to grasp the XSLT grammar of 'copying' and 'appending'.
Sample XML:
<root>
<document n="1">
<p>
<title>title here</title>
<seg>Lorem ipsum <id>foo</id> dolor sit amet, consectetur adipiscing elit.
Quisque a orci <ad>foo</ad> non mauris convallis imperdiet consequat nec
purus. Cras mollis lacus vel lectus facilisis, non
hendrerit velit tempor. Phasellus <id>foo</id> tempor urna vel accumsan
dignissim.</seg>
<seg>Aliquam porta eu nunc sed laoreet.
Sed non <od>foo</od> nulla consectetur, lobortis tortor ac,
placerat <ad>foo</ad> nunc. Nulla viverra finibus est nec efficitur. Donec
nisi nisl, <id>foo</id> tincidunt dapibus purus pretium, rhoncus volutpat
tortor. Cras fringilla tellus tortor, at
ultricies mi cursus at. Nulla facilisi.</seg>
<seg>Quisque id mi nisl. In in mauris id leo malesuada hendrerit.
Orci varius natoque
penatibus et magnis dis <od>foo</od> parturient montes, <ad>foo</ad> nascetur ridiculus
mus. Nulla sit amet
commodo mauris.</seg>
</p>
</document>
<document n="2">
<p>
<title>title here</title>
<seg>Lorem ipsum dolor <ad>foo</ad> sit <od>foo</od> amet, consectetur adipiscing elit.
Quisque a orci non mauris <id>foo</id> convallis imperdiet consequat nec
purus. Cras mollis lacus vel lectus facilisis, non
hendrerit velit tempor. Phasellus tempor urna vel accumsan
dignissim.</seg>
<seg>Aliquam porta eu nunc sed laoreet.
Sed non nulla <ad>foo</ad> consectetur, lobortis tortor ac,
placerat nunc. Nulla <id>foo</id> viverra finibus est nec efficitur. Donec
nisi <od>foo</od> nisl, tincidunt dapibus purus pretium, rhoncus volutpat
tortor. Cras fringilla tellus tortor, at
ultricies mi cursus at. Nulla facilisi.</seg>
<seg>Quisque id mi nisl. In in mauris id leo malesuada hendrerit.
Orci varius natoque
penatibus <id>foo</id> et magnis dis parturient montes, nascetur ridiculus
mus. Nulla sit amet
commodo mauris.</seg>
</p>
</document>
XSL 3.0:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0">
<xsl:mode on-no-match="shallow-copy"/>
<xsl:output method="xml" indent="yes" />
<xsl:template match="p">
<xsl:apply-templates/>
<xsl:variable name="idadod" select=".//id | .//ad | .//od"/>
<xsl:for-each select="$idadod">
<sum><xsl:number count="$idadod" level="any" format="a"/></sum>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Current incorrect result:
<root>
<document n="1">
<title>title here</title>
<seg>Lorem ipsum <id>foo</id> dolor sit amet, consectetur adipiscing elit.
Quisque a orci <ad>foo</ad> non mauris convallis imperdiet consequat nec
purus. Cras mollis lacus vel lectus facilisis, non
hendrerit velit tempor. Phasellus <id>foo</id> tempor urna vel accumsan
dignissim.</seg>
<seg>Aliquam porta eu nunc sed laoreet.
Sed non <od>foo</od> nulla consectetur, lobortis tortor ac,
placerat <ad>foo</ad> nunc. Nulla viverra finibus est nec efficitur. Donec
nisi nisl, <id>foo</id> tincidunt dapibus purus pretium, rhoncus volutpat
tortor. Cras fringilla tellus tortor, at
ultricies mi cursus at. Nulla facilisi.</seg>
<seg>Quisque id mi nisl. In in mauris id leo malesuada hendrerit.
Orci varius natoque
penatibus et magnis dis <od>foo</od> parturient montes, <ad>foo</ad> nascetur ridiculus
mus. Nulla sit amet
commodo mauris.</seg>
<sum>a</sum>
<sum>b</sum>
<sum>c</sum>
<sum>d</sum>
<sum>e</sum>
<sum>f</sum>
<sum>g</sum>
<sum>h</sum>
</document>
<document n="2">
<title>title here</title>
<seg>Lorem ipsum dolor <ad>foo</ad> sit <od>foo</od> amet, consectetur adipiscing elit.
Quisque a orci non mauris <id>foo</id> convallis imperdiet consequat nec
purus. Cras mollis lacus vel lectus facilisis, non
hendrerit velit tempor. Phasellus tempor urna vel accumsan
dignissim.</seg>
<seg>Aliquam porta eu nunc sed laoreet.
Sed non nulla <ad>foo</ad> consectetur, lobortis tortor ac,
placerat nunc. Nulla <id>foo</id> viverra finibus est nec efficitur. Donec
nisi <od>foo</od> nisl, tincidunt dapibus purus pretium, rhoncus volutpat
tortor. Cras <ad>foo</ad> fringilla tellus tortor, at
ultricies mi cursus at. Nulla facilisi.</seg>
<seg>Quisque id mi nisl. In in mauris id leo malesuada hendrerit.
Orci varius natoque
penatibus <id>foo</id> et magnis dis parturient montes, nascetur ridiculus
mus. Nulla sit amet
commodo mauris.</seg>
<sum>a</sum>
<sum>b</sum>
<sum>c</sum>
<sum>d</sum>
<sum>e</sum>
<sum>f</sum>
<sum>g</sum>
</document>
Desired outcome (sample):
<root>
<document n="1">
<title>title here</title>
<seg>Lorem ipsum <id>foo</id><sum>a</sum> dolor sit amet, consectetur adipiscing elit.
Quisque a orci <ad>foo</ad><sum>b</sum> non mauris convallis imperdiet consequat nec
purus. Cras mollis lacus vel lectus facilisis, non
hendrerit velit tempor. Phasellus <id>foo</id><sum>c</sum> tempor urna vel accumsan
dignissim.</seg>
<seg>Aliquam porta eu nunc sed laoreet.
Sed non <od>foo</od><sum>d</sum> nulla consectetur, lobortis tortor ac,
placerat <ad>foo</ad><sum>e</sum> nunc. Nulla viverra finibus est nec efficitur. Donec
nisi nisl, <id>foo</id><sum>f</sum> tincidunt dapibus purus pretium, rhoncus volutpat
tortor. Cras fringilla tellus tortor, at
ultricies mi cursus at. Nulla facilisi.</seg>
<seg>Quisque id mi nisl. In in mauris id leo malesuada hendrerit.
Orci varius natoque
penatibus et magnis dis <od>foo</od><sum>g</sum> parturient montes, <ad>foo</ad><sum>h</sum> nascetur ridiculus
mus. Nulla sit amet
commodo mauris.</seg>
</document>
.....
</root>
Everything is in XSLTfiddle here Thanks very much.
Upvotes: 1
Views: 20
Reputation: 66781
If you want to produce a <sum>
immediately following each <id>
, <ad>
, and <od>
, then move that inside of a template that matches on them. Copy their content, and then generate the <sum>
You had been producing all of them after processing each <p>
element.
Instead, add a template to match on the <p>
and simply process it's children, and in the template matching these <id>
, <ad>
, and <od>
elements, copy their content and then produce the <sum>
element.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0">
<xsl:mode on-no-match="shallow-copy"/>
<xsl:output method="xml" indent="yes" />
<xsl:template match="p">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="id | ad | od">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
<sum><xsl:number count="id | ad | od" from="p" format="a"/></sum>
</xsl:template>
</xsl:stylesheet>
Upvotes: 1