[xsl] Grouping and Insertion

Subject: [xsl] Grouping and Insertion
From: Jeff Sese <jsese@xxxxxxxxxxxx>
Date: Fri, 17 Nov 2006 16:13:00 +0800
Hi,

I have a source xml that needs to be inserted with new contents from a separate xml file.

source xml:

<root>
   <entry id="1" type="T" n="1">
       <!-- some more nodes here -->
   </entry>
   <entry id="1" type="T" n="1" n-mod="a">
       <!-- some more nodes here -->
   </entry>
   <entry id="1" type="T" n="2">
       <!-- some more nodes here -->
   </entry>
   <entry id="1" type="T" n="3">
       <!-- some more nodes here -->
   </entry>
   <entry id="1" type="T" n="4">
       <!-- some more nodes here -->
   </entry>
   <entry id="1" type="T" n="5">
       <!-- some more nodes here -->
   </entry>
</root>

reference xml:

<root>
<entry id="1" type="T" n="1"/>(<xref target="1" type="T" n="1">1</xref>) <!-- more nodes here 1 --><entry id="1" type="T" n="1" n-mod="a"/>(<xref target="1" type="T" n="1a">1a</xref>) <!-- more nodes here 2 --><entry id="1" type="T" n="1-5"/>(<xref target="1" type="T" n="1-5">1-5</xref>) <!-- more nodes here 3 --><entry id="1" type="T" n="2"/>(<xref target="1" type="T" n="2">2</xref>) <!-- more nodes here 4 -->
</root>


target xml output:

<root>
   <entry id="1" type="T" n="1">
       <!-- some more nodes here -->
   </entry>
   <new.entry>
      <!-- more nodes here 1 -->
   </new.entry>
   <entry id="1" type="T" n="1" n-mod="a">
       <!-- some more nodes here -->
   </entry>
   <new.entry>
      <!-- more nodes here 2 -->
   </new.entry>
   <entry id="1" type="T" n="2">
       <!-- some more nodes here -->
   </entry>
   <new.entry>
      <!-- more nodes here 4 -->
   </new.entry>
   <entry id="1" type="T" n="3">
       <!-- some more nodes here -->
   </entry>
   <entry id="1" type="T" n="4">
       <!-- some more nodes here -->
   </entry>
   <entry id="1" type="T" n="5">
       <!-- some more nodes here -->
   </entry>
   <new.entry>
      <!-- more nodes here 3 -->
   </new.entry>
</root>

Basically the requirements is for each entry in the source xml, look for a corresponding entry element in the reference xml (with same attributes) get the nodes after the (<xref></xref>) nodes and insert it after the entry as a child of a new.entry element.

I think that this is possible using keys, however i'm not that familiar with the use of keys.

This is my xsl file:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; xmlns:xs="http://www.w3.org/2001/XMLSchema"; exclude-result-prefixes="xs">
<xsl:output method="xml" version="1.0" encoding="UTF-8"/>
<xsl:param name="new.entry.file" as="xs:anyURI"/>
<xsl:variable name="new.entries" as="element()+" select="document($new.entry.file)//entry"/>
<xsl:key name="new.entry" match="node()[name()!='entry']" use="generate-id(preceding-sibling::entry[1])"/>
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="entry">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
<xsl:if test="if (exists(@n-mode)) then exists($new.entries[@id=current()/@id][@type=current()/@type][@n=current()/@n][@n-mod=current()/@n-mod]) else exists($new.entries[@id=current()/@id][@type=current()/@type][@n=current()/@n])">
<new.entry>
<xsl:apply-templates select="if (exists(@n-mode)) then $new.entries[@id=current()/@id][@type=current()/@type][@n=current()/@n][@n-mod=current()/@n-mod]/key('new.entry',generate-id())[position()>3] else $new.entries[@id=current()/@id][@type=current()/@type][@n=current()/@n][not(exists(@n-mod))]/key('new.entry',generate-id())[position()>3]"/>
</new.entry>
</xsl:if>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>


And using saxon8 I get this:

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <entry id="1" type="T" n="1">
       <!-- some more nodes here -->
   </entry>
   <new.entry><!-- more nodes here 1 --></new.entry>
   <entry id="1" type="T" n="1" n-mod="a">
       <!-- some more nodes here -->
   </entry>
   <new.entry><!-- more nodes here 1 --></new.entry>
   <entry id="1" type="T" n="2">
       <!-- some more nodes here -->
   </entry>
   <new.entry><!-- more nodes here 4 --></new.entry>
   <entry id="1" type="T" n="3">
       <!-- some more nodes here -->
   </entry>
   <entry id="1" type="T" n="4">
       <!-- some more nodes here -->
   </entry>
   <entry id="1" type="T" n="5">
       <!-- some more nodes here -->
   </entry>
</root>

--
*Jeferson L. Sese*
Asiatype Incorporated
Suite 114, Columbia Tower, Ortigas Ave.,
Greenhills, Mandaluyong City 1550 Philippines

Current Thread