如何使用XSLT比较(部分)使用XSLT的XML文档的子树,并根据比较结果作为单个标签返回布尔值?
问题描述:
假设存在一个软件系统,该系统可以使用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中是完全不可能的?
答
沿
<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))
)。