2014-07-05 59 views
0

我有兩個需要以特殊方式組合的XML文檔。將兩個具有相似模式的XML文檔組合起來

舉一個簡單的例子,我就乾脆把兩個文件到一個:

<?xml version="1.0" encoding="utf-8" ?> 
<data> 
    <config1> 
     <option1 type="a">A</option1> 
     <option2 type="b">B</option2> 
     <option3 type="c">C</option3> 
    </config1> 
    <config2> 
     <option2 type="bb">BB</option2> 
     <option4>D</option4> 
    </config2> 
</data> 

所以,我需要合併CONFIG1CONFIG2這個結果:

<?xml version="1.0" encoding="UTF-8"?> 
<data> 
    <config> 
    <option1 type="a">A</option1> 
    <option2 type="bb">BB</option2> 
    <option3 type="c">C</option3> 
    <option4>D</option4> 
    </config> 
</data> 

轉型規則是:

  1. Ge從CONFIG1噸選項,如果存在CONFIG2沒有這樣的選擇
  2. 否則獲取該選項從CONFIG2從CONFIG2
  3. 獲取的選擇,如果它們不存在於CONFIG1

我製作了以下XSLT:

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

    <xsl:template match="/*"> 
    <xsl:copy> 
     <config> 
     <!-- Select options from config 1. --> 
     <xsl:for-each select="config1/*"> 
      <xsl:choose> 
      <!-- Leave option as is. --> 
      <xsl:when test="not(/data/config2/*[name() = name(current())])"> 
       <xsl:copy-of select="."/> 
      </xsl:when> 
      <!-- Overwrite option. --> 
      <xsl:otherwise> 
       <xsl:copy-of select="/data/config2/*[name() = name(current())]"/> 
      </xsl:otherwise> 
      </xsl:choose> 
     </xsl:for-each> 

     <!-- Select options from config 2. --> 
     <xsl:for-each select="config2/*"> 
      <!-- Append "new" option --> 
      <xsl:if test="not(/data/config1/*[name()=name(current())])"> 
      <xsl:copy-of select="."/> 
      </xsl:if> 
     </xsl:for-each> 
     </config> 
    </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

它的工作,但看起來跛腳。

很多XSL大師更喜歡apply-templates for for-each。

是否有可能以這種方式重寫我的模板?

回答

2

舉一個簡單的例子,我就乾脆把兩個文件放到一個:

這不是一個好主意,因爲處理兩個文件是不一樣的處理兩個節點集的同一文件。因此,假設你處理的文檔是:

<?xml version="1.0" encoding="utf-8" ?> 
<data> 
    <config1> 
     <option1 type="a">A</option1> 
     <option2 type="b">B</option2> 
     <option3 type="c">C</option3> 
    </config1> 
</data> 

還有另一個文件:

file2.xml

<?xml version="1.0" encoding="utf-8" ?> 
<data> 
    <config2> 
     <option2 type="bb">BB</option2> 
     <option4>D</option4> 
    </config2> 
</data> 

你可以使用下面的樣式表:

XSLT 1.0

<?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:variable name="config2" select="document('file2.xml')/data/config2" /> 

<xsl:template match="/"> 
    <data> 
     <config> 
      <xsl:apply-templates select="data/config1/*[not(name()=name($config2/*))] | $config2/*"/> 
     </config> 
    </data> 
</xsl:template> 

<xsl:template match="data/*/*"> 
    <xsl:copy-of select="."/> 
</xsl:template> 

</xsl:stylesheet> 

獲得這樣的結果:

<?xml version="1.0" encoding="UTF-8"?> 
<data> 
    <config> 
     <option1 type="a">A</option1> 
     <option3 type="c">C</option3> 
     <option2 type="bb">BB</option2> 
     <option4>D</option4> 
    </config> 
</data> 
相關問題