Reputation: 356
I have two input files: file1.xml and file2.xml, with same structure but different contents (of source
and target
nodes).
file1.xml (simplified version)
<?xml version="1.0" encoding="UTF-8"?>
<xliff>
<file>
<body>
<trans-unit id="MDSD_0">
<source>Gestioni els seus favorits</source>
<target>Gestioni els seus favorits</target>
</trans-unit>
<trans-unit id="MDSD_1">
<source>Favorits</source>
<target>Favorits</target>
</trans-unit>
</body>
</file>
</xliff>
file2.xml (simplified version)
<?xml version="1.0" encoding="UTF-8"?>
<xliff>
<file>
<body>
<trans-unit id="MDSD_0">
<source>Manage your bookmarks</source>
<target>Manage your bookmarks</target>
</trans-unit>
<trans-unit id="MDSD_1">
<source>Bookmarks</source>
<target>Bookmarks</target>
</trans-unit>
</body>
</file>
</xliff>
I would like to take all content from file1.xml except the source node, that I want from file2.xml. In other words, I want to replace source
in file1.xml with source
in file2.xml.
I am tempted to do it in Perl or PHP, but I think in XSLT it would be more efficient. However, I'm a bit stuck.
My stylesheet:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:template match="source">
<source>
<xsl:value-of select="document('file2.xlf')//source" />
</source>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
This produces the following output:
<?xml version="1.0" encoding="UTF-8"?>
<xliff>
<file>
<body>
<trans-unit id="MDSD_0">
<source>Manage your bookmarks</source>
<target>Gestioni els seus favorits</target>
</trans-unit>
<trans-unit id="MDSD_1">
<source>Manage your bookmarks</source> <!-- this one is wrong -->
<target>Favorits</target>
</trans-unit>
</body>
</file>
</xliff>
As you can see, it's using the content from only the first source node in file2.xml to replace all source nodes in file1.xml.
I suppose I would need to make my selection somehow based on the position or where the id
of the parent trans-unit
is the same. I have tried with
<xsl:value-of select="document('file2.xlf')//source/parent::trans-unit[@id= current()]" />
but that gives me <source/>
.
I'd be thankful for any tips.
My stylesheet is XSLT version 1 but I suppose I could use XLST 2.0 if necessary (I am using Oxygen and free versions of Saxon).
Upvotes: 0
Views: 322
Reputation: 116959
Assuming you want to lookup the source
value by matching the id
of the parent trans-unit
, you could do:
<xsl:value-of select="document('file2.xml')/xliff/file/body/trans-unit[@id=current()/../@id]/source" />
In XSLT 2.0, you can make this easier (and more efficient) by defining a key as:
<xsl:key name="src" match="source" use="../@id" />
and then use it as:
<xsl:value-of select="key('src', ../@id, document('file2.xml'))" />
Upvotes: 1
Reputation: 167401
Change
<xsl:template match="source">
<source>
<xsl:value-of select="document('file2.xlf')//source" />
</source>
</xsl:template>
to
<xsl:template match="source">
<xsl:copy-of select="key('ref', ../@id, document('file2.xlf'))/source" />
</xsl:template>
with <xsl:key name="ref" match="trans-unit" use="@id"/>
added to the stylesheet (and make sure in oXygen you use Saxon 9 to have XSLT 2.0 support).
Upvotes: 1