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).
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'))" />