2013-03-16 57 views
0

我有以下XML:通過xslt屬性值合併2個或更多xml?

<PCstore> 
    <StoreList> 
     <Store id="001"> 
      <ItemList> 
       <Items laptop="DELL" price="300"/> 
       <Items laptop="gateway" price="450"/> 
       <Items screen="LG" price="200"/> 
      </ItemList> 
     </Store> 
    </StoreList> 
</PCstore> 

我有合併:

<PCstore> 
    <StoreList> 
     <Store id="002"> 
      <ItemList> 
       <Items laptop="gateway" price="650"/> 
       <Items screen="LG" price="200/> 
       <Items speakers="sony" price="50"/> 
      </ItemList> 
     </Store> 
    </StoreList> 
</PCstore> 

的願望輸出ifiltering屬性(筆記本= 「網關」):

<PCstore> 
    <StoreList> 
     <Store id="001"> 
      <ItemList> 
       <Items laptop="gateway" price="450"/> 
      </ItemList> 
     </Store> 
     <Store id="002"> 
      <ItemList> 
       <Items laptop="gateway" price="650"/> 
      </ItemList> 
     </Store> 
    </StoreList> 
</PCstore> 

等等更多xml3.xml,xml4.xml 等...

我沒有我嘗試過的代碼,我在XSLT上有點新,我希望有人能幫助我。

UPDATE

我嘗試這樣的代碼,但它不工作...

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

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

    <xsl:template match="Items"> 
    <xsl:copy> 
     <xsl:apply-templates select="@* | node()" /> 
     <xsl:apply-templates 
     select="document('xml2.xml') 
       /PCstore/StoreList/Store/ItemList[@id = current()/../@id] 
        /Items[@laptop = current()/@value]/*" /> 
    </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 
+0

是文件的數量將被限制到某個數字,還是會有無限數量?另外,任何不同的文件是否包含相同的商店ID?如果是這樣,你會在這種情況下發生什麼? – 2013-03-16 14:59:08

+0

它不應該有相同的商店。 對於限制,可以說我將有大約20 xmls,我必須合併,但如果我可以得到至少2 xmls合併將是偉大的,我猜我只需要應用相同的xsl輸出和一個新的XML。 謝謝 – 2013-03-16 18:46:07

回答

1

如果你只能使用XSLT1.0,一個辦法做到這一點會將xml文件的列表作爲參數傳遞給XSLT。例如:

<xsl:param name="filelist"> 
    <files> 
     <file>xml2.xml</file> 
     <!-- We can place here xml3.xml and so on --> 
    </files> 
</xsl:param> 

(因此,在這種情況下,我假設你應用XSLT到第一xml1.xml,而你只能在任何其它文件作爲參數傳遞)。

但是,在XSLT1.0中,您將需要使用擴展函數將此參數作爲節點集處理。執行<xsl:for-each select="$filelist/files/file">將導致錯誤「引用變量或參數'文件'必須計算爲節點列表」。因此,您需要使用擴展功能將其轉換爲node-set。在我的例子,我將使用微軟的在我的例子之一,但根據您的平臺,您可以使用exslt.org/common

下面是在這種情況下

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:msxml="urn:schemas-microsoft-com:xslt" 
    extension-element-prefixes="msxml"> 

    <xsl:output omit-xml-declaration="yes" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:param name="filelist"> 
     <files> 
     <file>xml2.xml</file> 
     </files> 
    </xsl:param> 

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

    <xsl:template match="StoreList"> 
     <xsl:copy> 
     <xsl:apply-templates select="@* | node()"/> 
     <xsl:for-each select="msxml:node-set($filelist)/files/file"> 
      <xsl:apply-templates select="document(text())/PCstore/StoreList/Store"/> 
     </xsl:for-each> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="Items[not(@laptop='gateway')]"/> 
</xsl:stylesheet> 

全XSLT當應用於你的XSLT如下它輸出

<PCstore> 
    <StoreList> 
     <Store id="001"> 
     <ItemList> 
      <Items laptop="gateway" price="450"/> 
     </ItemList> 
     </Store> 
     <Store id="002"> 
     <ItemList> 
      <Items laptop="gateway" price="650"/> 
     </ItemList> 
     </Store> 
    </StoreList> 
</PCstore> 

請注意,這些文件必須存在才能工作。如果您傳入不存在的文件的名稱,則會發生錯誤。

+0

謝謝,我申請了這個選項並且工作得很完美,我只是可以感謝你的時間併爲這個解決方案工作,我想你救了我一會兒,我還有一些改變要做。 謝謝Tim! 如果我需要一些幫助,有什麼辦法與您聯繫? – 2013-03-17 19:12:51

+0

嗨,我怎麼能夠發送params列表到xsl,在這種情況下的文件列表? 如果可能,還有「品牌」列表? (生成過濾器) – 2013-03-17 19:59:52

+0

這取決於你使用的是什麼平臺/語言(例如,php,asp,c#)。如果你無法解決這個問題,那麼可以隨時在StackOverflow上提出一個全新的問題,並且有人可以幫助你! – 2013-03-17 20:51:25

0

如果你可以使用XSLT 2.0,您可以使用collection() ...

xml1.xml

<PCstore> 
    <StoreList> 
     <Store id="001"> 
      <ItemList> 
       <Items laptop="DELL" price="300"/> 
       <Items laptop="gateway" price="450"/> 
       <Items screen="LG" price="200"/> 
      </ItemList> 
     </Store> 
    </StoreList> 
</PCstore> 

xml2.xml

<PCstore> 
    <StoreList> 
     <Store id="002"> 
      <ItemList> 
       <Items laptop="gateway" price="650"/> 
       <Items screen="LG" price="200"/> 
       <Items speakers="sony" price="50"/> 
      </ItemList> 
     </Store> 
    </StoreList> 
</PCstore> 

XSLT 2.0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:param name="type" select="'laptop'"/> 
    <xsl:param name="brand" select="'gateway'"/> 

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

    <xsl:template match="/"> 
     <PCstore> 
      <StoreList> 
       <xsl:apply-templates select="collection('file:///C:/store_test?select=*.xml')/PCstore/StoreList/Store"/> 
      </StoreList> 
     </PCstore> 
    </xsl:template> 

    <xsl:template match="Items[not(@*[name()=$type]=$brand)]"/> 

</xsl:stylesheet> 

輸出

<PCstore> 
    <StoreList> 
     <Store id="001"> 
      <ItemList> 

       <Items laptop="gateway" price="450"/> 

      </ItemList> 
     </Store> 
     <Store id="002"> 
      <ItemList> 
       <Items laptop="gateway" price="650"/> 


      </ItemList> 
     </Store> 
    </StoreList> 
</PCstore> 
+0

感謝您的解決方案,我很抱歉,我沒有嘗試過,因爲我需要合併超過1 xml。 但是,我檢查代碼,也許,它可能是有用的參數(品牌)插入XML。 太感謝了。 – 2013-03-17 19:17:57