Search code examples
xmlxsltxml-namespacessaxonxliff

Namespaces preventing transformation


I am running the following transformation:

java -jar saxon9.jar -it:main -xsl:my.xsl dir="ca-ES"

The "ca-ES" contains XLIFF files which have the following root element:

<xliff xmlns="urn:oasis:names:tc:xliff:document:1.1"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:cba="http://www.softcon.de/XML-schema/de.softcon.cba.itembuilder.xliff-supplement"
       version="1.1"
       xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.1 xliff-core-1.1.xsd">

The transformation uses identical files from a secondary input folder and generates as many structurally identical files as found in the input folder.

If I remove the first namespace (i.e. xmlns="urn:oasis:names:tc:xliff:document:1.1") from the root (i.e. xliff), then the transformation works like a charm. However, if I keep it, then it doesn't work.

The part that is not working is the template that matches source in the primary input file and replaces it with the source from the secondary input file):

<xsl:copy-of select="key('ref', ../@id, doc($secondary-input))/source" />

By not working I mean that the source from the primary input file is in the output rather than the expected source node from the secondary input. So it seems the namespace is getting in the way of the matching.

Looking for solutions I have tried adding the xpath-default-namespace attribute on the document element of the stylesheet:

<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xpath-default-namespace="urn:oasis:names:tc:xliff:document:1.1"
    version="2.0">

but then the source node from the primary input is kept in the output (that is, it's not replaced with the one from the secondary input).

I have also tried adding this prefix and then using it in the stylesheet to match nodes (e.g. match="xlf:source"), but then there is no source node at all in the output:

<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xlf="urn:oasis:names:tc:xliff:document:1.1"
    version="2.0">

I'll be grateful for some tips.

I'm using XSLT 2.0 and saxonb9-1-0-8j.

UPDATE

Adding one primary input file sample (named ca-ES_blabla.xlf, taken from the folder ca-ES):

<?xml version="1.0" encoding="UTF-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cba="http://www.softcon.de/XML-schema/de.softcon.cba.itembuilder.xliff-supplement" version="1.1" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.1 xliff-core-1.1.xsd">
  <file datatype="html" original="project.properties" source-language="ca">
    <body>
      <trans-unit id="MDSD_0" xml:space="default">
        <source>Gestiona les adreces d'interès</source>
        <target>Gestiona les adreces d'interès</target>
        <context-group name="era">
          <context context-type="x-property-id">bookmarkHeaderText</context>
        </context-group>
      </trans-unit>
      <trans-unit id="7" xml:space="default">
        <source>&lt;b&gt;Sempre rebrà un avís quan arribi a un punt a partir del qual no pugui tornar enrere.&lt;/b&gt;&lt;br /&gt;</source>
        <target>&lt;b&gt;Sempre rebrà un avís quan arribi a un punt a partir del qual no pugui tornar enrere.&lt;/b&gt;&lt;br /&gt;</target>
        <prop-group name="item_description">
          <prop prop-type="x-inquiry-nr">4</prop>
          <prop prop-type="x-type">question</prop>
        </prop-group>
      </trans-unit>
    </body>
  </file>
<!-- the xliff document might contain several <file> nodes -->
</xliff>

one secondary input file sample (named en-GB_blabla.xlf, taken from the folder en-GB):

<?xml version="1.0" encoding="UTF-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cba="http://www.softcon.de/XML-schema/de.softcon.cba.itembuilder.xliff-supplement" version="1.1" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.1 xliff-core-1.1.xsd">
  <file datatype="html" original="project.properties" source-language="en-GB">
    <body>
      <trans-unit id="MDSD_0" xml:space="default">
        <source>Manage your bookmarks</source>
        <target>Manage your bookmarks</target>
        <context-group name="era">
          <context context-type="x-property-id">bookmarkHeaderText</context>
        </context-group>
      </trans-unit>
      <trans-unit id="7" xml:space="default">
        <source>&lt;b&gt;You will always receive a warning before reaching a point where you cannot go back.&lt;/b&gt;&lt;br /&gt;</source>
        <target>&lt;b&gt;You will always receive a warning before reaching a point where you cannot go back.&lt;/b&gt;&lt;br /&gt;</target>
        <prop-group name="item_description">
          <prop prop-type="x-inquiry-nr">4</prop>
          <prop prop-type="x-type">question</prop>
        </prop-group>
      </trans-unit>
    </body>
  </file>
<!-- the xliff document might contain several <file> nodes -->
</xliff>

and the stylesheet:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xpath-default-namespace="urn:oasis:names:tc:xliff:document:1‌​.1"
    version="2.0">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
    <xsl:strip-space elements="*"/>

    <!-- run as: 
    $> java -jar saxon9.jar -it:main -xsl:this_stylesheet.xsl dir="xx-XX"      -->

    <!-- this captures the folder parameter given in the call -->  
    <xsl:param name="dir" select="dir" />

    <!-- this template iterates through the files in the input folder --> 
    <xsl:template name="main">
        <xsl:variable name="input-files" select="concat($dir, '?select=*.xlf')" />
        <xsl:apply-templates select="collection($input-files)"/>
    </xsl:template>

    <!-- this template defines the name of the output folder and files -->
    <xsl:template match="/">
        <xsl:variable name="output-name" select="replace(
            tokenize(document-uri(/), '/')[last()], 
            '(.+)\.xlf', 
            '$1_bilingual.xlf'
            )"/>
        <xsl:result-document href="{$dir}_output/{$output-name}">
            <xsl:apply-templates/>
        </xsl:result-document>
    </xsl:template>

    <!-- this template fetches the source from the English files --> 
    <xsl:key name="ref" match="trans-unit" use="@id"/> 
    <xsl:template match="source">
        <xsl:variable name="input-uri" select="document-uri(/)" />
        <!-- <xsl:message><xsl:value-of select="$input-uri" /></xsl:message> -->
        <xsl:variable name="secondary-input" select="replace($input-uri, $dir, 'en-GB')"/>
        <xsl:copy-of select="key('ref', ../@id, doc($secondary-input))/source" />
    </xsl:template>

    <!-- this part generates the output --> 
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

Solution

  • It seems to be a namespace problem, when I copy over the value "urn:oasis:names:tc:xliff:document:1.1" from the source to the stylesheet as xpath-default-namespace="urn:oasis:names:tc:xliff:document:1.1" the code works.

    I am not sure which characters you have in your stylesheet code (oXygen asked me to enable some language support when pasting your code) but somehow the strings

    "urn:oasis:names:tc:xliff:document:1.1"
    "urn:oasis:names:tc:xliff:document:1‌​.1"
    

    are not equal:

    var s1 = "urn:oasis:names:tc:xliff:document:1.1";
    var s2 = "urn:oasis:names:tc:xliff:document:1‌​.1";
    document.writeln('<code>' + s1 + ' === ' + s2 + ' : ' + (s1 === s2) + '<\/code>');

    It might be that the namespace in your stylesheet contains one or more https://en.wikipedia.org/wiki/Zero-width_non-joiner after the first digit 1.