2017-02-27 53 views
1

我有兩個需要合併的XML文檔。每個元素都有一個定義的ID。如果一個元素在兩個文檔中都是唯一的 - >將被添加到結果中,否則 - 屬性將被合併。XSLT合併兩個文檔中元素的屬性

main.xml中

<main> 
    <el id="1" attr1="value1" /> 
    <el id="2" attr2="value2" default-attr="def" /> 
</main> 

snippet.xml在EL

<main> 
    <el id="2" attr2="new value2" new-attr="some value" /> 
    <el id="3" attr3="value3" /> 
</main> 

爲result.xml

<main> 
    <el id="1" attr1="value1" /> 
    <el id="2" attr2="new value2" default-attr="def" new-attr="some value" /> 
    <el id="3" attr3="value3" /> 
</main> 

屬性合併[@ id = 2]並從snippet.xml覆蓋值。

我已經試過這樣:

merge.xlst

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

    <xsl:param name="snippetDoc" select="document(snippet.xml)" /> 

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

    <xsl:template match="el"> 
     <xsl:copy> 
      <!-- how to distinguish between @ids of two documents? --> 
      <xsl:copy-of select="$snippetDoc/main/el/[@id = @id]/@*" /> 
      <xsl:apply-templates select="@*" /> 
     </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

但它需要能夠在兩筆相同的屬性來區分。更重要的是,這不會複製snippet.xml中的獨特元素。

感謝您的幫助!

回答

1

你正在尋找的是這樣的你也應該把這個<xsl:apply-templates select="@*" />所以以後你可以採取的事實,新屬性將覆蓋,如果編寫的任何現有屬性優勢表達....

<xsl:copy-of select="$snippetDoc/main/el[@id=current()/@id]/@*" /> 

他們具有相同的名稱。

要在代碼片段中添加主文檔中沒有匹配元素的元素,您需要在匹配main元素的模板中執行此操作。

<xsl:template match="main"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
      <xsl:copy-of select="$snippetDoc/main/el[not(@id=current()/el/@id)]" /> 
     </xsl:copy>  
    </xsl:template> 

試試這個XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 

    <xsl:param name="snippetDoc" select="document('snippet.xml')" /> 

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

    <xsl:template match="el"> 
     <xsl:copy> 
      <!-- how to distinguish between @ids of two documents? --> 
      <xsl:apply-templates select="@*" /> 
      <xsl:copy-of select="$snippetDoc/main/el[@id=current()/@id]/@*" /> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="main"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
      <xsl:copy-of select="$snippetDoc/main/el[not(@id=current()/el/@id)]" /> 
     </xsl:copy>  
    </xsl:template> 

</xsl:stylesheet> 

請注意,node()實際上是短手*|text()|comment()|processing-instruction()這樣做node()|comment()實際上是不必要的。