troubleshooting Question

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

Avatar of Grant Rogers
Grant RogersFlag for United Kingdom of Great Britain and Northern Ireland asked on
Web Languages and StandardsXML
4 Comments2 Solutions372 ViewsLast Modified:
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>

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>

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>

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>

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
Join the community to see this answer!
Join our exclusive community to see this answer & millions of others.
Unlock 2 Answers and 4 Comments.
Join the Community
Learn from the best

Network and collaborate with thousands of CTOs, CISOs, and IT Pros rooting for you and your success.

Andrew Hancock - VMware vExpert
See if this solution works for you by signing up for a 7 day free trial.
Unlock 2 Answers and 4 Comments.
Try for 7 days

”The time we save is the biggest benefit of E-E to our team. What could take multiple guys 2 hours or more each to find is accessed in around 15 minutes on Experts Exchange.

-Mike Kapnisakis, Warner Bros