2013-05-01 63 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>