Используйте XSLT для объединения коллекции файлов XML и фильтрации данных

58
8

У меня есть коллекция многих 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 имеют одинаковое содержание tuv/seg EN-GB, сохраняйте их только с отдельным ES-ES-содержимым. Вот почему tu 22004D0068 и tu 22004D0069 должны быть сохранены, но tu 22004D0070 не должен (его ES-ES является дубликатом 22004D0069).

Мне удалось написать таблицу стилей, которая объединяет все файлы, но не удаляет ненужные элементы tuv (то есть DE-DE) и не отфильтровывает весь элемент tu с содержимым tuv/seg EN-GB и ES-ES, который уже находится в другой 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. Благодарю.

спросил(а) 2014-09-07T23:32:00+04:00 6 лет назад
1
Решение
69

Образ мышления XSLT немного привыкает.

Я вижу, что сначала вы находите все отдельные значения, и это нормально. Но тогда эта строка должна быть исправлена:

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

В приведенной выше строке применяются шаблоны (обрабатывает ввод) ко всем элементам tu, которые имеют одно из различных значений. Я понимаю, что вы хотите обрабатывать только один элемент tu на одно отличное значение. Но какой? Это имеет значение? Вы можете попробовать с первым, добавив еще один предикат: position()=1 или [1] для краткости.

ответил(а) 2014-09-08T00:54:00+04:00 6 лет назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема