まず、「等しい」という関係はその名前を持つことはできません。
「等しい」とは、その関係が同値関係であることを意味します。定義により、等価関係~
は次のようになります。
再帰: x ~ x
.
対称: もしそうx ~ y
ならy ~ x
他動詞: ifx ~ y
と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 ~ y
これで、とがわかりましたy ~ z
。ただし、明らかにこれは当てはまりません。x ~ z
これは、関係を「一致」と呼んでおり、「等しい」ではなくリラックスしたものだと言っています。
上記の調整による問題の解決策は次のとおりです。
XPath 1.0 (XSLT 1.0 変換内で使用される) には範囲変数がないため、これは単一の XPath 式では表現できないことに注意してください。
<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