2013-07-29 66 views
0

假設存在一個軟件系統,該系統可以使用XSLT在XML消息中指定某個謂詞。具體而言:將輸入文檔轉換爲以下格式的輸出文檔:<predicate>true</predicate>(或<predicate>false</predicate>)。如何使用XSLT比較(部分)使用XSLT的XML文檔的子樹,並根據比較結果作爲單個標籤返回布爾值?

對於一些簡單的情況下(如消息包含XPath),這是相當瑣碎,但我現在需要寫一個XSLT進行類似如下:

<change> 

    <!-- state before change --> 
    <item> 
    <name> 
     <first>...</first> 
     <last>...</last> 
    </name> 
    <something> 
     ... 
    </something> 
    </item> 

    <!-- state after change --> 
    <item> 
    <name> 
     <first>...</first> 
     <last>...</last> 
    </name> 
    <something> 
     ... 
    </something> 
    </item> 

</change> 

而且我想返回<predicate>true</predicate>了一個突變的定義,如果:

  • 的之前或狀態(或兩者)後實際上包含something數據的子樹(因爲這部分是可選的),所以基本上change/item[1]/something | change/item[2]/something,
  • 兩個都有任何something刪除數據的之前和之後的狀態彼此不完全相同。

第二部分可以是像以下僞代碼:$before變量是change/item[1]/something與任何現有的子樹something從它移除,$after變量是change/item[2]/something與任何現有的子樹something從它移除,然後也許類似not(deep-equal($before,$after)) .. 。?

任何人在這裏都有任何想法如何使用XSLT 2.0來做到這一點,因爲我懷疑這在XSLT 1.0中是完全不可能的?

回答

0

沿

<xsl:template match="change"> 
    <xsl:choose> 
    <xsl:when test="item[1]/something | item[2]/something"> 
     <xsl:variable name="before" as="element(item)"> 
     <xsl:apply-templates select="item[1]" mode="rs"/> 
     </xsl:variable> 
     <xsl:variable name="after" as="element(item)"> 
     <xsl:apply-templates select="item[2]" mode="rs"/> 
     </xsl:variable> 
     <predicate><xsl:value-of select="not(deep-equal($before,$after))"/></predicate> 
    </xsl:when> 
    <xsl:otherwise> 
     <predicate>false</predicate> 
    </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

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

<xsl:template match="something" mode="rs"/> 

未測試線嘗試,但應該給你一個想法。它基本上在兩個item元素上運行mode="rs"remove-something)中的變換以剝離something元素,然後它進行您發佈的比較(not(deep-equal($before,$after)))。