2017-06-18 164 views
0

我有兩個輸入文件: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中獲得。換句話說,我想用file2.xml中的source替換file1.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()]" /> 

但是那給了我<source/>

我會很感激任何提示。我的樣式表是XSLT版本1,但我想我可以在必要時使用XLST 2.0(我使用的是氧氣和免費版本的Saxon)。

回答

1

假設你想通過匹配父trans-unitid來查找source值,你可以這樣做:

<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'))" /> 
+0

XSLT 1.0的第一個解決方案不起作用。它產生''。我還沒有嘗試過的第二種解決方案,但它看起來與Martin提供的解決方案一樣,所以它應該可以工作。謝謝! – msoutopico

+0

它適用於我 - 但後來我的文件被命名爲'file2.xml'(正如您的問題所述),而不是您的示例代碼中使用的'file2.xlf'。 –

+0

你說得對,我的錯。我選擇你的答案是更完整(第1版和第2版的解決方案),並且是第一個發佈的答案。謝謝。 – msoutopico

1

變化

<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"/>加入到樣式表(並確保在氧氣使用撒克遜9有XSLT 2.0的支持)。

+0

謝謝,像撒克遜9.7.0.15一樣的魅力 – msoutopico

相關問題