RE: [xsl] Adding element to xml snippet using xslt

Subject: RE: [xsl] Adding element to xml snippet using xslt
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Tue, 22 Feb 2005 22:49:19 -0000
> I have to migrate the nodes from fileA(source doc) and fileB 
> (which is 
> also a xml doc) to an output xml doc. The xslt is run on 
> fileA in such a 
> manner that all nodes from fileA are copied over(preserving 
> their order) 
> and the common nodes that are present in fileA as well as fileB are 
> merged using the xslt and the output of the merge is written to the 
> output file.
> 
> In this particular case, 'drillOutDir' is present in fileB 
> only, which 
> needs to be also present in the ouput file too. The 'started' 
> element is 
> present in fileA as well as fileB, but its version in fileB 
> is newer and 
> hence i need to get the started element from fileB in my output file.
> 
> FileA contains --
> <abc:configuration 
> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";  
> xsi:schemaLocation="http://oracle.com/
> xmlns/abcst/configuration configuration.xsd" locale="en" >
> <started status="true"></started>
> <server></server>
> ....
> </abc:configuration>
> -----------------------------
> 
> FileB contains --
> 
> <abc:configuration 
> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
> xsi:schemaLocation="http://oracle.com/ xmlns/abcst/configuration 
> configuration.xsd" locale="en" >
> <drillOutDir></drillOutDir>
> <started status="true">This application was stopped.</started>
> <server></server>
> ....
> </abc:configuration>
> ------------------------------
> 
> Output file should contain --
> 
> <abc:configuration 
> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";  
> xsi:schemaLocation="http://oracle.com/
> xmlns/abcst/configuration configuration.xsd" locale="en" >
> <drillOutDir></drillOutDir>
> <started status="true">This application was stopped.</started>
> <server></server>
> 
> ....
> </abc:configuration>

I've no idea what's in the "...." so I'll assume it doesn't exist.

It's not entirely clear to me what the general rules are: it's easy to do a
stylesheet that works for this example and then produces results you
consider wrong for the next example. What do you want to happen, for
example, if the status attribute is present in both documents but with
different values?

Here's a generic approach that uses XSLT 2.0 grouping.

<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
xmlns:abc="abc.uri">

<xsl:output indent="yes"/>
<xsl:template name="copy">
  <xsl:param name="group"/>
  <xsl:element name="{name($group[1])}">
    <xsl:copy-of select="$group/@*"/>
    <xsl:for-each-group select="$group/*" group-by="node-name(.)">
       <xsl:call-template name="copy">
         <xsl:with-param name="group" select="current-group()"/>
       </xsl:call-template>
    </xsl:for-each-group>
    <xsl:copy-of select="$group[1]/text()"/>
  </xsl:element>
</xsl:template>

<xsl:template name="main">
  <xsl:call-template name="copy">
    <xsl:with-param name="group" select="document(('a.xml', 'b.xml'))/*"/>
  </xsl:call-template>
</xsl:template>

</xsl:stylesheet>

Note this uses a named entry point, it doesn't have a principal source
document, this means that the two inputs are treated completely
symmetrically. It recurses down the tree in much the same way as a standard
apply-templates, but at each stage it passes a pair of elements, one from
each tree (if both exist) or a single element if it's present in one one
tree. It relies on the automatic elimination of duplicate attributes by the
XSLT processor. If two elements or attributes in the two documents have the
same name but different content, it outputs one of them, fairly arbitrarily.

To run this in Saxon 8.x:

java -jar saxon8.jar -it main test.xsl

This design is harder to realise in 1.0 because grouping is more difficult,
especially across two documents.

Note that there are no references to any elements in your source documents.
As far as I can tell from your description, the merging you want to achieve
is independent of the detailed structure of the XML, so a generic solution
is much preferable.

Michael Kay
http://www.saxonica.com/

Current Thread