XSL:通过比较节点的子节点来比较节点 [英] XSL: Comparing nodes by comparing their child nodes

查看:27
本文介绍了XSL:通过比较节点的子节点来比较节点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望能够根据两个节点的子节点的值来比较两个节点.使用 = 运算符测试节点相等性只是比较各个节点的字符串值.我想根据它们的子节点中的值来比较它们.

I would like to be able to compare two nodes based on the values of their child nodes. Testing node equality with the = operator just compares the string values of the respective nodes. I would like to compare them based on values in their child nodes.

更具体地说,我希望 (下面)相等,因为 的值@id 元素相同,具有匹配的 @type 属性也具有匹配的 @id 属性.

To be a bit more specific, I would like <a> and <b> (below) to be equal, because the values of @id are the same for <c> elements that have matching @type attributes also have matching @id attributes.

<a>
    <c type="type-one" id="5675"/>
    <c type="type-two" id="3423"/>
    <c type="type-three" id="9088"/>
</a>
<b>
    <c type="type-one" id="5675"/>
    <c type="type-two" id="3423"/>
</b>

但这些会有所不同:

<a>
    <c type="type-one" id="5675"/>
</a>
<b>
    <c type="type-one" id="2342"/>
</b>

我开始看到的唯一解决方案是与 for-each 语句进行费力的比较,如果可能,我想避免这种情况.

The only solution I can begin to see involves a laborious comparison with a for-each statement, which I would like to avoid if possible.

如果可能,我想坚持使用 XSLT 1.0.我正在使用 xsltproc.

If possible I would like to stick with XSLT 1.0. I am using xsltproc.

推荐答案

首先,称为等于"的关系不能有这个名称.

等于"表示该关系是等价关系.根据定义,任何等价关系 ~ 必须是:

"Equals" means that the relation is an equivalence relation. By definition any equivalence relation ~ must be:

  1. 反身:x ~ x .

对称:如果x ~ y 那么y ~ x

传递:如果 x ~ yy ~ z 那么 x ~ z .

Transitive: if x ~ y and y ~ z then x ~ z .

下面是一个例子,表明提议的等于"关系不是可传递的:

x 是:

<a>
    <c type="type-one" id="5675"/>
    <c type="type-two" id="3423"/>
    <c type="type-three" id="9088"/>
</a>

y 是:

<b>
    <c type="type-one" id="5675"/>
    <c type="type-two" id="3423"/>
    <c type="type-four" id="1234"/>
</b>

z 是:

<b>
    <c type="type-three" id="3333"/>
    <c type="type-four" id="1234"/>
</b>

现在,我们可以看到 x ~ yy ~ z.然而,显然这不成立:x ~ z

Now, we can see that x ~ y and y ~ z. However, clearly this doesn't hold: x ~ z

这就是说,我称这种关系为匹配",它是宽松的,而不是等于".

This said, I am calling the relation "matches" and it is relaxed and not "equals".

这里有一个解决问题的方法,经过上面的调整:

请注意,这不能用单个 XPath 表达式表示,因为 XPath 1.0(在 XSLT 1.0 转换中使用)没有范围变量.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="/*">
     <xsl:call-template name="matches">
       <xsl:with-param name="pElem1" select="a"/>
       <xsl:with-param name="pElem2" select="b"/>
     </xsl:call-template>
 </xsl:template>

 <xsl:template name="matches">
   <xsl:param name="pElem1" select="/.."/>
   <xsl:param name="pElem2" select="/.."/>

   <xsl:variable name="vMisMatch">
       <xsl:for-each select="$pElem1/c[@type = $pElem2/c/@type]">
        <xsl:if test=
           "$pElem2/c[@type = current()/@type and not(@id = current()/@id)]">1</xsl:if>
       </xsl:for-each>
   </xsl:variable>

   <xsl:copy-of select="not(string($vMisMatch))"/>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于以下 XML 文档时:

<t>
    <a>
        <c type="type-one" id="5675"/>
        <c type="type-two" id="3423"/>
        <c type="type-three" id="9088"/>
    </a>
    <b>
        <c type="type-one" id="5675"/>
        <c type="type-two" id="3423"/>
    </b>
</t>

产生了想要的、正确的结果:

true

在此 XML 文档上应用相同的转换时:

<t>
    <a>
        <c type="type-one" id="5675"/>
        <c type="type-two" id="3423"/>
        <c type="type-three" id="9088"/>
    </a>
    <b>
        <c type="type-one" id="5675"/>
        <c type="type-two" id="9876"/>
    </b>
</t>

再次产生正确的结果:

false

这篇关于XSL:通过比较节点的子节点来比较节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆