Avatar of Grant Rogers
Grant Rogers
Flag 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
Web Languages and StandardsXML

Avatar of undefined
Last Comment
Grant Rogers

8/22/2022 - Mon
ASKER CERTIFIED SOLUTION
Gertone (Geert Bormans)

Log in or sign up to see answer
Become an EE member today7-DAY FREE TRIAL
Members can start a 7-Day Free trial then enjoy unlimited access to the platform
Sign up - Free for 7 days
or
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.
Not exactly the question you had in mind?
Sign up for an EE membership and get your own personalized solution. With an EE membership, you can ask unlimited troubleshooting, research, or opinion questions.
ask a question
Gertone (Geert Bormans)

Note that you don't need to do this trickery in XSLT2.
SOLUTION
Grant Rogers

Log in or sign up to see answer
Become an EE member today7-DAY FREE TRIAL
Members can start a 7-Day Free trial then enjoy unlimited access to the platform
Sign up - Free for 7 days
or
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.
Not exactly the question you had in mind?
Sign up for an EE membership and get your own personalized solution. With an EE membership, you can ask unlimited troubleshooting, research, or opinion questions.
ask a question
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.
I started with Experts Exchange in 2004 and it's been a mainstay of my professional computing life since. It helped me launch a career as a programmer / Oracle data analyst
William Peck