使用另一个文件中同一节点的值替换节点值

Posted

技术标签:

【中文标题】使用另一个文件中同一节点的值替换节点值【英文标题】:Replace node value using value from same node in another file 【发布时间】:2017-11-20 16:51:30 【问题描述】:

我有两个输入文件:file1.xml 和 file2.xml,结构相同但内容不同(sourcetarget 节点)。

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 中获取这些内容。换句话说,我想将file1.xml中的source替换为file2.xml中的source

我很想在 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 中的所有源节点。

我想我需要根据位置或父trans-unitid 相同的位置进行选择。我试过了

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

但这给了我&lt;source/&gt;

如有任何提示,我将不胜感激。

我的样式表是 XSLT 版本 1,但我想我可以在必要时使用 XLST 2.0(我使用的是 Oxygen 和 Saxon 的免费版本)。

【问题讨论】:

【参考方案1】:

假设您想通过匹配父 idid 来查找 source 值,您可以这样做:

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

在 XSLT 2.0 中,您可以通过将 key 定义为:

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

然后将其用作:

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

【讨论】:

XSLT 1.0 的第一个解决方案不起作用。它产生&lt;source/&gt;。第二种解决方案我没有尝试过,但它似乎与 Martin 提供的相同,所以它应该可以工作。谢谢! 它对我有用 - 但是我的文件被命名为 file2.xml(如您的问题中所述),而不是您的示例代码中使用的 file2.xlf 你是对的,我的错。我选择您的答案是因为它更完整(v.1 和 v.2 的解决方案)并且是第一个发布的。谢谢。【参考方案2】:

改变

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

&lt;xsl:key name="ref" match="trans-unit" use="@id"/&gt; 添加到样式表(并确保在 oXygen 中使用 Saxon 9 以获得 XSLT 2.0 支持)。

【讨论】:

以上是关于使用另一个文件中同一节点的值替换节点值的主要内容,如果未能解决你的问题,请参考以下文章

Python Pandas Dataframe 用同一会话的另一个单元格的值替换单元格值

XSLT 替换属性值和文本节点中的文本

剑指 Offer II 054. 所有大于等于节点的值之和

在MYSQL中如何用一个字段的值替换另一个字段的值

Powershell 中非常大的 XML 文件

用另一个文件中的值替换一个文件不能正常工作