Reputation: 1
I have several files that I want to merge, ignoring empty elements.
For example : File 1:
<ds>
<sk>
<f1>1</f1>
<f2>2</f2>
</sk>
<sk>
<f1>3</f1>
<f2>4</f2>
</sk>
</ds>
file 2 :
<ds>
<ac>
<g1>9</f1>
<g2>10</f2>
</ac>
<ac>
<g1>11</f1>
<g2>12</f2>
</ac>
</ds>
and File 3:
<ds>
<rs>
<k1>A</f1>
<k2>B</f2>
<k3></k3>
</rs>
<rs>
<k1>C</f1>
<k2>B</f2>
<k3/>
</rs>
</ds>
I want as outpout:
<ds>
<sk>
<f1>1</f1>
<f2>2</f2>
</sk>
<sk>
<f1>3</f1>
<f2>4</f2>
</sk>
<ac>
<g1>9</f1>
<g2>10</f2>
</ac>
<ac>
<g1>11</f1>
<g2>12</f2>
</ac>
<rs>
<k1>A</f1>
<k2>B</f2>
</rs>
<rs>
<k1>C</f1>
<k2>B</f2>
</rs>
</ds>
I have tried this as xslt :
<?xml version="1.0" ?>
<xsl:transform
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xml:space="preserve"
version="1.0">
<xsl:output indent="yes"/>
<xsl:template match="/ds">
<xsl:copy-of select="document('File1')/ds/sk"/>
<xsl:copy-of select="document('File2')/ds/ac"/>
<xsl:copy-of select="document('File3')/ds/rs"/>
</xsl:template>
</xsl:transform>
Input is File1. Files are merge but I cannot figure how to remove empty elements like or in File3. Any idea ?
Upvotes: 0
Views: 284
Reputation: 1
I cannot figure why but the problem is solved using this xslt
<xsl:template match="/">
<xsl:copy>
<xsl:apply-templates select="document('File1')/ds/sk" />
<xsl:apply-templates select="document('File2')/ds/ac" />
<xsl:apply-templates select="document('File3')/ds/rs" />
</xls:copy>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[not(*)][not(normalize-space())]" />
Note : yours was performing well using Altova (with msxml as parser). In my code (powerbuilder), i need to use this one ...
Upvotes: 0
Reputation: 70618
Assuming all your XML file were actually well-formed, you should start off by using the XSLT identity transform
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
Then, instead of doing xsl:for-each
, do xsl:apply-templates
instead.
<xsl:apply-templates select="document('File1')/ds/sk" />
<xsl:apply-templates select="document('File2')/ds/ac" />
<xsl:apply-templates select="document('File3')/ds/rs" />
Note, you may not necessarily need to use the document
function on File1
if that happens to be the input file of the XSLT itself.
Then to remove empty elements, just add a template like this:
<xsl:template match="*[not(*)][not(normalize-space())]" />
Try this XSLT
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" encoding="UTF-8" indent="yes" />
<xsl:template match="/">
<xsl:apply-templates select="document('File1')/ds/sk" />
<xsl:apply-templates select="document('File2')/ds/ac" />
<xsl:apply-templates select="document('File3')/ds/rs" />
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[not(*)][not(normalize-space())]" />
</xsl:transform>
Upvotes: 2