2013-07-29 57 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)))。