Заменить значение узла, используя значение из того же узла в другом файле

У меня есть два входных файла: file1.xml и file2.xml, с одинаковой структурой, но разным содержимым (из source а также target узлы).

file1.xml (упрощенная версия)

<?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 (упрощенная версия)

<?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>

Я хотел бы взять весь контент из file1.xml, за исключением исходного узла, который я хочу из file2.xml. Другими словами, я хочу заменить source в file1.xml с source в файле2.xml.

Я испытываю желание сделать это на Perl или PHP, но я думаю, что в XSLT это было бы более эффективно. Тем не менее, я немного застрял.

Моя таблица стилей:

<?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>

Это дает следующий вывод:

<?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>

Как вы можете видеть, он использует содержимое только первого исходного узла в file2.xml, чтобы заменить все исходные узлы в file1.xml.

Я полагаю, мне нужно было бы сделать свой выбор как-то на основе позиции или где id родителя trans-unit та же. Я пробовал с

<xsl:value-of select="document('file2.xlf')//source/parent::trans-unit[@id= current()]" />

но это дает мне <source/>,

Буду благодарен за любые советы.

Моя таблица стилей XSLT версии 1, но я полагаю, что при необходимости могу использовать XLST 2.0 (я использую Oxygen и бесплатные версии Saxon).

2 ответа

Решение

Предполагая, что вы хотите найти source значение путем сопоставления id родителя trans-unitВы могли бы сделать:

<xsl:value-of select="document('file2.xml')/xliff/file/body/trans-unit[@id=current()/../@id]/source" />

В XSLT 2.0 вы можете сделать это проще (и эффективнее), определив ключ как:

<xsl:key name="src" match="source" use="../@id" />

а затем использовать его как:

<xsl:value-of select="key('src', ../@id, document('file2.xml'))" />

+ Изменить

<xsl:template match="source">
        <source>
            <xsl:value-of select="document('file2.xlf')//source" />
        </source>
</xsl:template>

в

<xsl:template match="source">
        <xsl:copy-of select="key('ref', ../@id, document('file2.xlf'))/source" />
</xsl:template>

с <xsl:key name="ref" match="trans-unit" use="@id"/> добавлен в таблицу стилей (и убедитесь, что в oXygen вы используете Saxon 9 для поддержки XSLT 2.0).

Другие вопросы по тегам