productioncoder
productioncoder

Reputation: 4335

XSLT open other xml files

I am about to merge XML files (and adding meta information) whose relative path is specified in my input XML file. The files I want to merge are located in a subdirectory called "files" The structure of the input file is the following

<files>
   <file>
       <path>files/firstfile.xml</path>
   </file>
   <file>
       <path>files/secondfile.xml</path>
   </file>
</files>

The firstfile.xml and secondfile.xml have the following structure

    <tables>
        <table name = "...">
        ...
        </table>
        ...
    <tables>

I would like to put all table nodes of one file in a group and add meta information to it. So I wrote the following XSLT stylesheet:

   <xsl:template match="/">
    <tables>
          <xsl:apply-templates/>
    </tables>
</xsl:template>


<xsl:template name = "enrichWithMetaInformation" match = "file">
            <xsl:apply-templates select="document(./path)/tables">
                <xsl:with-param name="file" select="."/>
            </xsl:apply-templates>


</xsl:template>

<xsl:template match="tables">

    <group>
        <meta>
            ...Some meta data ...
        </meta>
        <xsl:copy-of select="./table"/>
    </group>
</xsl:template>

For every file I get an error:

The system could not find the file specified.

It states that an empty node set has been returned (so the file could not be loaded). Does anybody have an idea of how to fix this issue?

Cheers

Upvotes: 3

Views: 5519

Answers (2)

Michael Kay
Michael Kay

Reputation: 163322

Check that the base URI of the source document is known, for example by doing base-uri(/). This value is used for resolving the relative URI passed to document(), in the case where the argument is supplied as a node (or set of nodes).

Two common situations where the base URI is unknown are:

(a) if you supply the source document as an in-memory DOM

(b) if you supply the source document as an input stream or Reader with no known URI.

Upvotes: 2

Kevin Brown
Kevin Brown

Reputation: 8877

The argument to the document() function should be a string. Get the node value for path in variable concatting with the ./ and pass that in. I can do a quick test when I get to my computer but I think that is your issue. Here's an option:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="/">
    <tables>
        <xsl:apply-templates/>
    </tables>
</xsl:template>
<xsl:template match = "file">
    <xsl:variable name="filepath" select="concat('./',path)"/>
    <xsl:call-template name="tableprocessor">
        <xsl:with-param name="tables" select="document($filepath)/tables"/>
    </xsl:call-template>   
</xsl:template>
<xsl:template name="tableprocessor">
    <xsl:param name="tables"/>
    <group>
        <xsl:copy-of select="$tables"/>
    </group>
</xsl:template>
</xsl:stylesheet>

Upvotes: 1

Related Questions