Reputation: 177
I have two different xmls (unique reference is @id). Need to copy all child nodes of B.xml's "transunit/target" to A.xml's nodes when @id matches. Please have a look at A.xml and B.xml.
note: all the target content in B.xml is suffix by "Translated"
XSLT version 2.0 and processor Saxon EE/HE 9.X.X.X
A.xml
<concept id="001" xml:lang="en-us">
<title id="002">Notice</title>
<shortdesc id="003">This information U.S.A.</shortdesc>
<conbody id="004">
<p id="005">This product blah blah <companyname id="006">blah bla</companyname> No other warranty expressed or implied. </p>
<p id="007">This supersedes all previous notices.</p>
<section id="008">
<title id="009">COPYRIGHT LICENSE:</title>
<p id="010">This information contains <b id="011">in source language</b> , blah blah</p>
</section>
</conbody>
</concept>
B.xml
<root>
<transunit id="002">
<source>Notice</source>
<target>Translated:Notice</target>
</transunit>
<transunit id="003">
<source>This information U.S.A.</source>
<target>Translated:This information U.S.A.</target>
</transunit>
<transunit id="005">
<source>This product blah blah <companyname id="006" local-name="companyname">blah bla</companyname> No other warranty expressed or implied. </source>
<target>Translated:This product blah blah <companyname id="006" local-name="companyname">blah bla</companyname> No other warranty expressed or implied. </target>
</transunit>
<transunit id="007">
<source>This supersedes all previous notices.</source>
<target>Translated:This supersedes all previous notices.</target>
</transunit>
<transunit id="009">
<source>COPYRIGHT LICENSE:</source>
<target>Translated:COPYRIGHT LICENSE:</target>
</transunit>
<transunit id="010">
<source>This information contains <b id="011" local-name="b">in source language</b> , blah blah</source>
<target>Translated:This information contains <b id="011" local-name="b">in source language</b> , blah blah</target>
</transunit>
</root>
Expected result:
<concept id="001" xml:lang="en-us">
<title id="002">Translated:Notice</title>
<shortdesc id="003">Translated:This information U.S.A.</shortdesc>
<conbody id="004">
<p id="005">Translated:This product blah blah <companyname id="006">blah bla</companyname> No other warranty expressed or implied. </p>
<p id="007">Translated:This supersedes all previous notices.</p>
<section id="008">
<title id="009">Translated:COPYRIGHT LICENSE:</title>
<p id="010">Translated:This information contains <b id="011">in source language</b> , blah blah</p>
</section>
</conbody>
</concept>
I am trying something like:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">
<xsl:template match="node()">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[count(ancestor::*) != 0]" priority="2">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:variable name="id">
<xsl:value-of select="@id"/>
</xsl:variable>
<xsl:choose>
<xsl:when test="document('B.xml')//*[$id=@id]">
<xsl:for-each select="document('B.xml')//*[$id=@id]/target">
<xsl:message>i m hre</xsl:message>
<xsl:apply-templates/>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates/>
</xsl:otherwise>
</xsl:choose>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Upvotes: 0
Views: 99
Reputation: 12729
This XSLT 2.0 stylesheet ...
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output encoding="UTF-8" indent="yes" omit-xml-declaration="yes" />
<xsl:strip-space elements="*" />
<xsl:param name="translations" select="''" />
<xsl:variable name="valid-ids" as="xs:string*">
<xsl:if test="$translations ne ''">
<xsl:sequence select="document($translations)//*[target]/@id" />
</xsl:if>
</xsl:variable>
<xsl:key name="trans" match="*[@id][target]" use="@id" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="*[@id = $valid-ids]">
<xsl:variable name="id" select="@id" />
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:for-each select="document($translations)">
<xsl:apply-templates select="key('trans',$id)/target/node()" />
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
... applied using a command line like (for Saxon processor) ...
"C:\Program Files\Saxonica\SaxonHE9.5N\bin\transform" "-s:A.xml" "-xsl:sheet.xsl" "-o:outp.xml" "translations=B.xml"
... with the two given input files (A.xml being the main input document and B.xml referenced as a stylesheet parameter, yields ...
<concept id="001" xml:lang="en-us">
<title id="002">Translated:Notice</title>
<shortdesc id="003">Translated:This information U.S.A.</shortdesc>
<conbody id="004">
<p id="005">Translated:This product blah blah <companyname id="006" local-name="companyname">blah bla</companyname> No other warranty expressed or implied. </p>
<p id="007">Translated:This supersedes all previous notices.</p>
<section id="008">
<title id="009">Translated:COPYRIGHT LICENSE:</title>
<p id="010">Translated:This information contains <b id="011" local-name="b">in source language</b> , blah blah</p>
</section>
</conbody>
</concept>
You could enhance the functionality of this stylesheet, by including the doc-avail() function . Choose how to handle the translation document being specified but not available. A number of reasonable options would be possible to implement.
Thanks to Martin, here is an improved version of second template.
<xsl:template match="*[@id = $valid-ids]">
<xsl:copy>
<xsl:apply-templates select="@*,key('trans',@id, document($translations))/target/node()" />
</xsl:copy>
</xsl:template>
Upvotes: 1