0

I want to merge multiple xml files. I find a good command which merges perfectly two xml files Merge Command. so to merge multiple file, put the command into a shell script.

the script is as follow:

#!/bin/bash
for i in `ls recep` //recep is the directory containing the list of xmlfiles
do
saxon tt merge.xslt with=$i > aux //tt is a file, we create it and initiate 
                                    it to the first xml file 
cp aux  tt     
done
cat tt

however, the script excute only one merge

thank you for your help

1
  • XSLT 3.0 w3.org/TR/xslt-30 even in the open-source Saxon 9.8 HE has an xsl:merge instruction w3.org/TR/xslt-30/#merge-instruction you might be able to use with a collection for-each-source="uri-collection('recep/?select=*.xml')", to implement the whole merging with one transformation. Commented Jul 23, 2017 at 9:44

2 Answers 2

1

I created a simple test case to check your script. So I downloaded the merge.xslt file mentioned and created some files.

Overall, the test case looks like this:

tt:

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <List>
    <Field0>Value X</Field0>
  </List>
</root>

a1.xml - a4.xml in a sub-directory named recep with the FieldX values equal to the XML file number:

<root>
  <List>
    <Field1>Value X</Field1>
  </List>
</root>

Then I slightly modified your script to match my saxon installation:

#!/bin/bash
for i in `ls recep` 
do
  java -jar /pathToSaxon/saxon9he.jar --suppressXsltNamespaceCheck tt merge.xslt with=recep/$i > aux  
  cp aux tt     
done
cat tt

After executing the script tt contains:

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <List>
    <Field0>Value X</Field0>
    <Field1>Value X</Field1>
    <Field2>Value X</Field2>
    <Field3>Value X</Field3>
    <Field4>Value X</Field4>
  </List>
</root>

So the final result is:
I cannot reproduce your error. It must be something else like a missing directory name (ls recep/*) or so, because merge.xslt does work as expected.

Sign up to request clarification or add additional context in comments.

2 Comments

thank you a lot Dear ZX485, I replace "ls/recep" with "ls/recep/*" and it works perfectly.
it's okay Zx485 :)
0

As an alternative, in XSLT 3.0 it is also possible to execute the merge stylesheet on a collection of files, using uri-collection and transform and fold-left from https://www.w3.org/TR/xpath-functions-31/:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:math="http://www.w3.org/2005/xpath-functions/math"
    xmlns:mf="http://example.com/mf"
    exclude-result-prefixes="xs math mf"
    version="3.0">

    <xsl:param name="input-dir" as="xs:string?" select="'.'"/>
    <xsl:param name="file-selection-pattern" as="xs:string" select="'?select=*.xml'"/>

    <!-- saved merge.xslt from http://web.archive.org/web/20160809092524/http://www2.informatik.hu-berlin.de/~obecker/XSLT/#merge as original-merge.xslt -->
    <xsl:param name="merge-code-uri" as="xs:string" select="'original-merge.xslt'"/>
    <xsl:param name="merge-sheet" as="document-node()" select="doc($merge-code-uri)"/>

    <!-- 
    Call Saxon 9.8 with option -it to start with below template that allows merging a collection of files
    as specified by the parameters $input-dir and $file-selection-pattern.   
    -->
    <xsl:template name="xsl:initial-template">
        <xsl:variable name="input-uris" as="xs:anyURI*" select="uri-collection($input-dir || $file-selection-pattern)"/>
        <xsl:sequence select="mf:merge($input-uris)"/>
    </xsl:template>

    <xsl:function name="mf:merge" as="node()*">
        <xsl:param name="input-uris" as="xs:anyURI*"/>
        <xsl:sequence select="fold-left(tail($input-uris), doc(head($input-uris)), mf:merge#2)"/>
    </xsl:function>

    <xsl:function name="mf:merge" as="node()*">
        <xsl:param name="doc1" as="document-node()"/>
        <xsl:param name="doc2-uri" as="xs:string"/>
        <xsl:sequence select="transform(map { 
            'stylesheet-node' : $merge-sheet,
            'source-node' : $doc1,
            'stylesheet-params' : map { xs:QName('with') : $doc2-uri }
            })?output"/>
    </xsl:function>

</xsl:stylesheet>

A more detailed explanation is in http://xslt-3-by-example.blogspot.de/2017/07/functional-programming-with-fold-left.html.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.