2013-05-01 88 views
0

我有兩個我想合併的XML文檔。如何使用xslt將xml節點與某些條件組合?

forSale.xml:

<forSale> 
<game> 
    <cover>me3_cover.jpg</cover> 
    <title>Mass Effect 3</title> 
    <publisher>Electronic Arts</publisher> 
    <developer>BioWare</developer> 
    <genre>Role-Playing</genre> 
    <releaseDate> 
     <yyyy>2012</yyyy> 
     <mm>03</mm> 
     <dd>06</dd> 
    </releaseDate> 
    <esrbRating>M</esrbRating> 
    <platforms> 
     <platform>X360</platform> 
     <platform>PC</platform> 
     <platform>PS3</platform> 
     <platform>WIIU</platform> 
    </platforms> 
</game> 
<!--more games--> 
</forSale> 

reviews.xml:

<reviews> 
<game> 
    <title>Mass Effect 3</title> 
    <review> 
     <critic>Kevin VanOrd</critic> 
     <synopsis> 
      <![CDATA[some data]]> 
     </synopsis> 
     <pros> 
      <pro><![CDATA[some data]]></pro> 
      <pro><![CDATA[some data]]></pro> 
      <pro><![CDATA[some data]]></pro> 
      <pro><![CDATA[some data]]></pro> 
      <pro><![CDATA[some data]]></pro> 
     </pros> 
     <cons> 
      <con><![CDATA[some data]]></con> 
      <con><![CDATA[some data]]></con> 
     </cons> 
     <content> 
      <![CDATA[some data]]> 
      <p /> 
      <![CDATA[some data]]> 
      <p /> 
      <![CDATA[some data]]> 
      <p /> 
      <img url="me3_img1.jpg"><![CDATA[some data]]></img> 
      <![CDATA[some data]]> 
      <p /> 
      <![CDATA[some data]]> 
      <p /> 
      <img url="me3_img2.jpg"><![CDATA[some data]]></img> 
      <![CDATA[some data]]> 
      <p /> 
      <![CDATA[some data]]> 
      <p /> 
      <img url="me3_img3.jpg"><![CDATA[some data]]></img> 
      <![CDATA[some data]]> 
      <p /> 
      <![CDATA[some data]]> 
      <p /> 
      <img url="me3_img4.jpg"><![CDATA[some data]]></img> 
      <![CDATA[some data]]> 
      <p /> 
      <![CDATA[some data]]> 
      <p /> 
      <img url="me3_img5.jpg"><![CDATA[some data]]></img> 
      <![CDATA[some data]]> 
      <p /> 
      <![CDATA[some data]]> 
      <p /> 
      <img url="me3_img6.jpg"><![CDATA[some data]]></img> 
      <![CDATA[some data]]> 
      <p /> 
      <![CDATA[some data]]> 
      <p /> 
      <img url="me3_img7.jpg"><![CDATA[some data]]></img> 
      <![CDATA[some data]]> 
      <p /> 
      <![CDATA[some data]]> 
      <p /> 
      <img url="me3_img8.jpg"><![CDATA[some data]]></img> 
      <![CDATA[some data]]> 
      <p /> 
      <![CDATA[some data]]> 
     </content> 
    </review> 
</game> 
<!--more games--> 
</reviews> 

,然後我想輸出看起來像這樣:

<forSale> 
<game> 
    <cover>me3_cover.jpg</cover> 
    <title>Mass Effect 3</title> 
    <publisher>Electronic Arts</publisher> 
    <developer>BioWare</developer> 
    <genre>Role-Playing</genre> 
    <releaseDate> 
     <yyyy>2012</yyyy> 
     <mm>03</mm> 
     <dd>06</dd> 
    </releaseDate> 
    <esrbRating>M</esrbRating> 
    <platforms> 
     <platform>X360</platform> 
     <platform>PC</platform> 
     <platform>PS3</platform> 
     <platform>WIIU</platform> 
    </platforms> 
    <review> 
     <critic>Kevin VanOrd</critic> 
     <synopsis> 
      <![CDATA[some data]]> 
     </synopsis> 
     <pros> 
      <pro><![CDATA[some data]]></pro> 
      <pro><![CDATA[some data]]></pro> 
      <pro><![CDATA[some data]]></pro> 
      <pro><![CDATA[some data]]></pro> 
      <pro><![CDATA[some data]]></pro> 
     </pros> 
     <cons> 
      <con><![CDATA[some data]]></con> 
      <con><![CDATA[some data]]></con> 
     </cons> 
     <content> 
      <![CDATA[some data]]> 
      <p /> 
      <![CDATA[some data]]> 
      <p /> 
      <![CDATA[some data]]> 
      <p /> 
      <img url="me3_img1.jpg"><![CDATA[some data]]></img> 
      <![CDATA[some data]]> 
      <p /> 
      <![CDATA[some data]]> 
      <p /> 
      <img url="me3_img2.jpg"><![CDATA[some data]]></img> 
      <![CDATA[some data]]> 
      <p /> 
      <![CDATA[some data]]> 
      <p /> 
      <img url="me3_img3.jpg"><![CDATA[some data]]></img> 
      <![CDATA[some data]]> 
      <p /> 
      <![CDATA[some data]]> 
      <p /> 
      <img url="me3_img4.jpg"><![CDATA[some data]]></img> 
      <![CDATA[some data]]> 
      <p /> 
      <![CDATA[some data]]> 
      <p /> 
      <img url="me3_img5.jpg"><![CDATA[some data]]></img> 
      <![CDATA[some data]]> 
      <p /> 
      <![CDATA[some data]]> 
      <p /> 
      <img url="me3_img6.jpg"><![CDATA[some data]]></img> 
      <![CDATA[some data]]> 
      <p /> 
      <![CDATA[some data]]> 
      <p /> 
      <img url="me3_img7.jpg"><![CDATA[some data]]></img> 
      <![CDATA[some data]]> 
      <p /> 
      <![CDATA[some data]]> 
      <p /> 
      <img url="me3_img8.jpg"><![CDATA[some data]]></img> 
      <![CDATA[some data]]> 
      <p /> 
      <![CDATA[some data]]> 
     </content> 
    </review> 
</game> 
<!--more games--> 
</forSale> 

我有問題首先要說的是當reviews.xml中的<title>標籤和forSale.xml匹配時,那麼評論必須添加其他不是。我必須使用XSLT來做到這一點,我有迄今的代碼如下:

<forSale> 
<xsl:for-each select="document('forSale.xml')/forSale/game"> 
    <game> 
     <xsl:copy-of select="cover" /> 
     <xsl:copy-of select="title" /> 
     <xsl:variable name="title" select="title" /> 
     <xsl:copy-of select="publisher" /> 
     <xsl:copy-of select="developer" /> 
     <xsl:copy-of select="genre" /> 
     <xsl:copy-of select="releaseDate" /> 
     <xsl:copy-of select="esrbRating" /> 
     <xsl:copy-of select="platforms"/> 
      <xsl:template match="document('reviews.xml')/reviews/game"> 
      <xsl:choose> 
       <xsl:when test="./title = $title"> 
        <xsl:copy> 
         <xsl:apply-templates select="./review" /> 
        </xsl:copy> 
       </xsl:when> 
      </xsl:choose> 
     </xsl:template> 
    </game> 

</xsl:for-each> 
</forSale> 

再其次,我不知道如何複製<![CDATA[some data]]>完全一樣的。

任何幫助,將不勝感激!謝謝!

回答

1

基本上XSLT數據模型不純文本節點和CDATA部分區分這樣,無論您輸入有例如<foo>some data</foo><foo><![CDATA[some data]]></foo>未在XSLT處理器使用的輸入樹中建模。因此,你不能確保這樣的元素被照原樣複製。然而,您可以指示XSLT處理器使用例如CDATA部分輸出某些結果元素的內容作爲CDATA部分。

<xsl:output cdata-section-elements="foo bar"/> 

將確保XSLT轉換的序列化結果樹使用<foo><![CDATA[some data]]></foo><bar><![CDATA[a & b]]></bar>。然而,這些將會發生在這些名稱的所有元素上,而不僅僅是那些從具有CDATA節內容的輸入中複製的元素。你的問題的

+0

很好的解釋+1 – 2013-05-01 13:12:42

+0

馬丁,有沒有像「XSLT數據模型」。您可能想說「XPath數據模型」或「XML Infoset」? – 2013-05-02 01:35:54

+0

那麼XSLT使用「XPath數據模型」(http://www.w3.org/TR/xslt#data-model),所以在使用術語「XSLT數據模型」時我沒有看到任何錯誤。 – 2013-05-02 08:47:52

0

的問題的答案的第一部分是: 您可以使用相同的覺得像你一樣的第一個訪問第二個文件: 像這樣的東西應該做的:

   <xsl:for-each select="document('reviews.xml')/reviews/game[title = $title]"> 
        <xsl:copy> 
         <xsl:apply-templates select="review" /> 
        </xsl:copy> 
       </xsl:for-each> 

更新:生成CDATA。

我不知道是否以及如何在輸入中測試CDATA。但是你可以測試是否有可以逃脫的字符,但你不喜歡那樣並使用CDATA。 嘗試是這樣的:

<xsl:template match="text()"> 
    <xsl:choose> 
     <xsl:when test="contains(.,'&lt;')"> 
      <xsl:text disable-output-escaping="yes">&lt;![CDATA[</xsl:text> 
      <xsl:value-of disable-output-escaping="yes" select="."/> 
      <xsl:text disable-output-escaping="yes">]]&gt;</xsl:text> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:value-of select="."/> 
     </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 
0

完整的解決方案是這樣的:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:fo="http://www.w3.org/1999/XSL/Format"> 
    <xsl:output method="xml" indent="yes"/> 
    <xsl:strip-space elements="*"/> 
    <xsl:template match="/"> 
    <forSale> 
     <xsl:for-each select="document('Untitled1.xml')/forSale/game"> 
     <game> 
      <xsl:copy-of select="cover"/> 
      <xsl:copy-of select="title"/> 
      <xsl:variable name="title" select="title"/> 
      <xsl:copy-of select="publisher"/> 
      <xsl:copy-of select="developer"/> 
      <xsl:copy-of select="genre"/> 
      <xsl:copy-of select="releaseDate"/> 
      <xsl:copy-of select="esrbRating"/> 
      <xsl:copy-of select="platforms"/> 
      <xsl:for-each select="document('Untitled2.xml')/reviews/game"> 
      <xsl:choose> 
       <xsl:when test="./title = $title"> 
       <review> 
        <xsl:call-template name="checkChild"> 
        <xsl:with-param name="self" select="self::node()/review"/> 
        </xsl:call-template> 
       </review> 
       </xsl:when> 
      </xsl:choose> 
      </xsl:for-each> 
     </game> 
     </xsl:for-each> 
    </forSale> 
    </xsl:template> 

    <xsl:template name="checkChild"> 
    <xsl:param name="self"/> 
    <xsl:for-each select="$self/child::node()"> 
     <xsl:message> 
     <xsl:value-of select="name()"/> 
     </xsl:message> 
     <xsl:choose> 
     <xsl:when test="self::node()/name() = 'pros'"> 
      <pros> 
      <xsl:for-each select="pro"> 
       <pro> 
       <xsl:text disable-output-escaping="yes">&lt;![CDATA[</xsl:text> 
       <xsl:value-of select="."/> 
       <xsl:text disable-output-escaping="yes">]]&gt;</xsl:text> 
       </pro> 
      </xsl:for-each> 
      </pros> 

     </xsl:when> 
     <xsl:when test="self::node()/name() = 'synopsis'"> 
      <xsl:copy> 
      <xsl:text disable-output-escaping="yes">&lt;![CDATA[</xsl:text> 
      <xsl:value-of select="."/> 
      <xsl:text disable-output-escaping="yes">]]&gt;</xsl:text> 
      </xsl:copy> 
     </xsl:when> 
     <xsl:when test="self::node()/name() = 'cons'"> 
      <cons> 
      <xsl:for-each select="con"> 
       <con> 
       <xsl:text disable-output-escaping="yes">&lt;![CDATA[</xsl:text> 
       <xsl:value-of select="."/> 
       <xsl:text disable-output-escaping="yes">]]&gt;</xsl:text> 
       </con> 
      </xsl:for-each> 
      </cons> 
     </xsl:when> 
     <xsl:when test="self::node()/name() = 'content'"> 
      <content> 

      <xsl:for-each select="child::node()"> 
       <xsl:choose> 
       <xsl:when test="self::text()"> 
        <xsl:text disable-output-escaping="yes">&lt;![CDATA[</xsl:text> 
        <xsl:value-of select="."/> 
        <xsl:text disable-output-escaping="yes">]]&gt;</xsl:text> 
       </xsl:when> 
       <xsl:when test="self::node()/name()= 'img'"> 
        <xsl:element name="{name()}"> 
        <xsl:if test="@url"> 
         <xsl:attribute name="url"> 
         <xsl:value-of select="@url"/> 
         </xsl:attribute> 
        </xsl:if> 
        <xsl:text disable-output-escaping="yes">&lt;![CDATA[</xsl:text> 
        <xsl:value-of select="."/> 
        <xsl:text disable-output-escaping="yes">]]&gt;</xsl:text> 
        </xsl:element> 
       </xsl:when> 
       <xsl:otherwise> 
        <xsl:copy> 
        <xsl:copy-of select="node()"/> 
        </xsl:copy> 
       </xsl:otherwise> 
       </xsl:choose> 
      </xsl:for-each> 
      </content> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:copy> 
      <xsl:copy-of select="node()"/> 
      </xsl:copy> 
     </xsl:otherwise> 
     </xsl:choose> 

    </xsl:for-each> 
    </xsl:template> 


</xsl:stylesheet>