Link to home
Start Free TrialLog in
Avatar of Grant Rogers
Grant RogersFlag for United Kingdom of Great Britain and Northern Ireland

asked on

How do I merge multiple documents and store them in an xslt variable?

Hi guys,

The problem

I want to be able to merge multiple xml documents (with the same schema) into an xslt variable.  The reason why I want to do this is to reduce the number of output files that I am creating.

What I have implemented already

My steps so far to do this is to have:
1) An xsl file that converts the input xml to the output xml.
2) A UNIX shell script that finds all of the output xml files and creates an xml file that lists all of the files to be merged.
3) A second xsl file that merges all of the nodes together.
4) A thrid xsl file that does processesing on the merged file and gives the final output xml file.

This is obviously long winded and prone to error because I am creating more temporary files, but this is the only way I know how to do this.

Step 1 is complete so I will concentrate on other steps for now.
Step 2 is easy to do and I think the easiest way to supply multiple file names to an xsl processor (I did see a solution about passing a comma delimited list to a global parameter, but tokenising is not natively supported and the solution didn't look as clean as this one).

Here is an exmaple of file generated by the UNIX script:
<root>
	<file name="file1.xml" />
	<file name="file2.xml" />
	<file name="file3.xml" />
	...
</root>

Open in new window


Step 3 is complete.

Here is the xsl code used to merge all of the files:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:output method="xml" indent="yes"/>

	<xsl:template match="/">
		<root>
		<xsl:for-each select="/root/file">
			<xsl:apply-templates select="document(@name)/root/*"/>
		</xsl:for-each>
		</root>
	</xsl:template>

	<xsl:template match="rbam/*">
		<xsl:copy>
			<xsl:copy-of select="*"/>
		</xsl:copy>
	</xsl:template>
</xsl:stylesheet>

Open in new window


Step 4 is complete.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
	<xsl:output method="xml" indent="yes"/>
	<xsl:template match="/">
		<root>
		<xsl:variable name="uniqueNames" select="/root/a/name[not(. = ../preceding::name)]"/>
		<xsl:for-each select="$uniqueNames">
				<a>
				<name><xsl:value-of select="."/></name>
				<xsl:variable name="uniqueName" select="."/>
				<xsl:variable name="as" select="/root/a[name = $uniqueName and value = 'a']"/>
				<xsl:variable name="bs" select="/root/a[name = $uniqueName and value = 'b']"/>
				<xsl:variable name="cs" select="/root/a[name = $uniqueName and value = 'c']"/>
					<xsl:choose>
						<xsl:when test="$as">
							<value>a</value>
						</xsl:when>
						<xsl:when test="$cs and $bs">
							<value>a</value>
						</xsl:when>
						<xsl:when test="$bs">
							<value>b</value>
						</xsl:when>
						<xsl:when test="$cs">
							<value>c</value>
						</xsl:when>
					</xsl:choose>
				</a>
		</xsl:for-each>
		</root>
	</xsl:template>
</xsl:stylesheet>

Open in new window


What I have tried to get this working

I have tried to wrap the document merging inside a variable like so:
<xsl:template match="/">
	<xsl:variable name="mergedFiles">
		<xsl:for-each select="/rbam/file">
			<xsl:apply-templates select="document(@name)/root/*"/>
		</xsl:for-each>
	</xsl:variable>
	<xsl:message>
		<xsl:value-of select="count($mergedFiles)"/>
	</xsl:message>
	<xsl:for-each select="$mergedFiles">
		<xsl:copy-of select="."/>
	</xsl:for-each>
</xsl:template>

<xsl:template match="root/*">
	<xsl:copy>
		<xsl:copy-of select="*"/>
	</xsl:copy>
</xsl:template>

Open in new window


But I get an error when I try to run the transformation: Can not convert #RTREEFRAG to a NodeList!

I have read up about this error and it is suggested to use node-set in EXSLT.

Is this what I should be using or is there a better way to accomplish what I want?

Thanks
ASKER CERTIFIED SOLUTION
Avatar of Gertone (Geert Bormans)
Gertone (Geert Bormans)
Flag of Belgium image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Note that you don't need to do this trickery in XSLT2.
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Grant Rogers

ASKER

I have added my own comment as part of the solution because it provides a complete example of how to solve the original question with references.