2015-06-07 52 views
0

我有以下個XML:XSLT copy元素如果在第一XML不存在

car.xml:

<car ref-id="parts.xml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <color>red</color> 
    <tire>michelin</tire> 
    <engines> 
    <engine> 
     <model>Z</model> 
    </engine> 
    </engines> 
    <hifi>pioneer</hifi> 
</car> 

parts.xml:

<?xml version="1.0" encoding="UTF-8"?> 
<parts xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <engines> 
    <engine> 
     <model>X</model> 
    </engine> 
    <engine> 
     <model>Y</model> 
    </engine> 
    </engines> 
    <tire>goodyear</tire> 
    <color>black</color> 
    <airbag>true</airbag> 
</parts> 

I」 d喜歡將parts.xml與car.xml合併,但只想複製car.xml中不存在的parts.xml中的那些節點(不管它們的值如何)。

例如,我需要以下的輸出:

<car xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <color>red</color> 
    <tire>michelin</tire> 
    <engines> 
    <engine> 
     <model>Z</model> 
    </engine> 
    </engines> 
    <hifi>pioneer</hifi> 
    <airbag>true</airbag> 
</car> 

我被困在下面的轉型,其合併的所有元素:

<?xml version="1.0"?> 
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output method="xml" indent="yes" /> 

    <xsl:variable name="loc"> 
     <xsl:value-of select="car/@ref-id" /> 
    </xsl:variable> 

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

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

</xsl:transform> 

回答

1

這是一個相當尷尬的安排有,而解決方案 - 至少在XSLT 1.0中 - 同樣不容易:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:exsl="http://exslt.org/common" 
extension-element-prefixes="exsl"> 
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:template match="/car"> 
    <xsl:variable name="local-names"> 
     <xsl:for-each select="*"> 
      <name><xsl:value-of select="name()"/></name> 
     </xsl:for-each> 
    </xsl:variable> 
    <xsl:copy> 
     <xsl:copy-of select="*"/> 
     <xsl:copy-of select="document(@ref-id)/parts/*[not(name()=exsl:node-set($local-names)/name)]"/> 
    </xsl:copy> 
</xsl:template> 

</xsl:stylesheet> 
+0

Tricky!謝謝! – Bruckwald

+0

如果我將car.xml中的''更改爲'<引擎覆蓋=「true」>',並且只有在override =「false」時纔想從part.txt複製'', 要怎麼做?我用''加上了本地名稱,但拷貝的附加條件爲 'exsl:node-set($ local-names)/ attr ='false' '不起作用。 – Bruckwald

+0

請不要在評論中發佈代碼。或者將其添加到您的問題中(使用完整的代碼示例)或發佈一個新的代碼。 ---順便說一句,如果你可以控制輸入XML,考慮使用屬性(名稱或ID)來標識部件,而不是元素名稱。 –