使用XSLT合并XML文件集合并过滤数据

时间:2014-09-07 20:32:25

标签: xml xslt localization merge filtering

我有许多XML文件的集合,我必须在一个工具中导入,遗憾的是一次无法导入多个文件。所以我需要将它们合并到一个最终文件中。

这是我需要合并的三个被删除的示例文件(除输入文件3中的西班牙文本外,这三个文件都是相同的):

输入文件1:

<?xml version="1.0" encoding="UTF-16LE"?>
<!DOCTYPE tmx
SYSTEM "tmx14.dtd">
<tmx version="1.4">
<header o-tmf="Euramis" creationtool="tm3" creationtoolversion="8.20 from 29-08-2011 15:47" segtype="sentence" datatype="PlainText" adminlang="EN-US" srclang="EN-GB">
</header>
<body>
<tu>
<prop type="Txt::Doc. No.">22004D0069</prop>
<tuv lang="EN-GB">
<seg>Text in English: blabla</seg>
</tuv>
<tuv lang="DE-DE">
<seg>Text in German: blabla</seg>
</tuv>
<tuv lang="ES-ES">
<seg>Text in Spanish: blabla</seg>
</tuv>
</tu>
</body>
</tmx>

输入文件2:

<?xml version="1.0" encoding="UTF-16LE"?>
<!DOCTYPE tmx
SYSTEM "tmx14.dtd">
<tmx version="1.4">
<header o-tmf="Euramis" creationtool="tm3" creationtoolversion="8.20 from 29-08-2011 15:47" segtype="sentence" datatype="PlainText" adminlang="EN-US" srclang="EN-GB">
</header>
<body>
<tu>
<prop type="Txt::Doc. No.">22004D0070</prop>
<tuv lang="EN-GB">
<seg>Text in English: blabla</seg>
</tuv>
<tuv lang="DE-DE">
<seg>Text in German: blabla</seg>
</tuv>
<tuv lang="ES-ES">
<seg>Text in Spanish: blabla</seg>
</tuv>
</tu>
</body>
</tmx>

输入文件3:

<?xml version="1.0" encoding="UTF-16LE"?>
<!DOCTYPE tmx
SYSTEM "tmx14.dtd">
<tmx version="1.4">
<header o-tmf="Euramis" creationtool="tm3" creationtoolversion="8.20 from 29-08-2011 15:47" segtype="sentence" datatype="PlainText" adminlang="EN-US" srclang="EN-GB">
</header>
<body>
<tu>
<prop type="Txt::Doc. No.">22004D0068</prop>
<tuv lang="EN-GB">
<seg>Text in English: blabla</seg>
</tuv>
<tuv lang="DE-DE">
<seg>Text in German: blabla</seg>
</tuv>
<tuv lang="ES-ES">
<seg>Blablabla: a different text in Spanish</seg>
</tuv>
</tu>
</body>
</tmx>

这就是我想要实现的目标:

预期输出:

<?xml version="1.0" encoding="UTF-8"?>
<tmx xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl">
   <body>
      <tu>
         <prop type="Txt::Doc. No.">22004D0068</prop>
         <tuv lang="EN-GB">
            <seg>Text in English: blabla</seg>
         </tuv>
         <tuv lang="ES-ES">
            <seg>Blablabla: a different text in Spanish</seg>
         </tuv>
      </tu>
      <tu>
         <prop type="Txt::Doc. No.">22004D0069</prop>
         <tuv lang="EN-GB">
            <seg>Text in English: blabla</seg>
         </tuv>
         <tuv lang="ES-ES">
            <seg>Text in Spanish: blabla</seg>
         </tuv>
      </tu>
   </body>
</tmx>

因此,转型意味着:

  • 删除任何不符合EN-GB或ES-ES的语言
  • 如果两个或更多tu项具有相同的EN-GB tuv / seg内容,则仅保留具有不同ES-ES内容的tu项。这就是为什么应该保留tu 22004D0068和tu 22004D0069,但tu 22004D0070不应该(它的ES-ES是22004D0069的副本)。

我设法编写了合并所有文件的样式表,但没有删除不需要的tuv项目(即DE-DE),也没有使用EN-GB和ES过滤掉整个tu项目-ES tuv / seg已经在另一个tu中的内容。

这是我的样式表:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs"
    xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl" version="2.0">

    <xsl:output method="xml" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:variable name="collection">
        <xsl:copy-of select="collection('input_dir?strip-space=yes;select=*.tmx')/*"/>
    </xsl:variable>

    <xsl:variable name="tu" select="distinct-values($collection/tmx/body/tu/tuv)"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="/">
        <tmx>
            <body>
                <xsl:for-each select="$tu">
                    <xsl:apply-templates select="($collection/tmx/body/tu[tuv[@lang='EN-GB']=current()])"/>
                </xsl:for-each>
            </body>
        </tmx>
    </xsl:template>
</xsl:stylesheet>

这就是它的作用:

<?xml version="1.0" encoding="UTF-8"?>
<tmx xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl">
   <body>
      <tu>
         <prop type="Txt::Doc. No.">22004D0068</prop>
         <tuv lang="EN-GB">
            <seg>Text in English: blabla</seg>
         </tuv>
         <tuv lang="DE-DE"> <!-- German language should be left out -->
            <seg>Text in German: blabla</seg>
         </tuv>
         <tuv lang="ES-ES">
            <seg>Blablabla: a different text in Spanish</seg>
         </tuv>
      </tu>
      <tu>
         <prop type="Txt::Doc. No.">22004D0069</prop>
         <tuv lang="EN-GB">
            <seg>Text in English: blabla</seg>
         </tuv>
         <tuv lang="DE-DE"> <!-- German language should be left out -->
            <seg>Text in German: blabla</seg>
         </tuv>
         <tuv lang="ES-ES">
            <seg>Text in Spanish: blabla</seg>
         </tuv>
      </tu>
      <tu> <!-- this whole tu item should not be in my output -->
         <prop type="Txt::Doc. No.">22004D0070</prop>
         <tuv lang="EN-GB">
            <seg>Text in English: blabla</seg>
         </tuv>
         <tuv lang="DE-DE">
            <seg>Text in German: blabla</seg>
         </tuv>
         <tuv lang="ES-ES">
            <seg>Text in Spanish: blabla</seg>
         </tuv>
      </tu>
   </body>
</tmx>

我想我已经过了一半,但我被困住了,需要一些帮助。有人可以给我一个暗示或指出我正确的方向吗?我们对XLST有非常基本的了解,你可以看到。感谢。

1 个答案:

答案 0 :(得分:0)

XSLT的思维方式需要一些时间来适应。

我看到你先找到所有不同的值,这很好。但是这条线应该修好:

<xsl:apply-templates select="($collection/tmx/body/tu[tuv[@lang='EN-GB']=current()])"/>

上面的行将模板(处理输入)应用于具有其中一个不同值的所有 tu元素。我知道你只想在每个不同的值处理一个tu元素。但是哪一个?有关系吗?您可以在第一个谓词中尝试添加另一个谓词:position()=1[1]