jbrehr
jbrehr

Reputation: 815

XSLT appending an element and incremented letter while copying XML file

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

Answers (1)

Mads Hansen
Mads Hansen

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

Related Questions