假设我将拥有2个xml文档 XML1
<req>
<a name="1">
<a name="2"/>
</a>
</req>
和 XML2
<r>
<b id="1">
<a name="1">
<a name="2"/>
</a>
</b>
<b id="2">
<a name="3">
<a name="4">
<a name="5"/>
</a>
</a>
</b>
</r>
我想要做的是使用xml1作为搜索要包含的元素所需节点的列表。在中,我想只返回那些只包含那些在xml1中指定的子元素“a”的“b”元素而没有其他元素(它仍然可以包含具有不同名称的其他元素),但是我想要弄清楚如何确保“a”的每个子元素也被指定为“a”而不是其他元素。
基本上我只能找到那些在“xml1”中指定“a”元素的“b”元素,并且具有完全相同的“a”子元素(可以忽略任何其他元素)
for $r in $xml2/r/b
where (every $a
in $r/a
satisfies $a/@name = $xml1/req/a/@name)
return $r
到目前为止我尝试了什么,但如果我理解正确,这应该只检查第一层
编辑:以防万一,更好的搜索规则规范:“b”节点是一个结果节点,当且仅当它包含所有且仅包含xml1中指定的“a”节点和两个“a”节点时如果它们具有相同的名称和相同的“a”节点子节点,则它们是相同的。
编辑2: 为澄清,以下两个“b”相等
<r>
<b id="1">
<a name="1">
<a name="2"/>
</a>
</b>
</r>
和
<r>
<b id="1">
<a name="1">
<a name="2"/>
<d/>
</a>
<c/>
</b>
</r>
答案 0 :(得分:1)
以下解决方案假设每个级别上可能有多个a
元素,并且它假定这些元素的顺序必须相同:
declare variable $xml1 := <req>...</req>;
declare variable $xml2 := <r>...</r>;
declare function local:deep-equal-a($xml, $find) {
let $xas := $xml/a, $fas := $find/a
return count($xas) = count($fas) and (
every $test in for-each-pair($xas, $fas, function($xa, $fa) {
$xa/@name = $fa/@name and local:deep-equal-a($xa, $fa)
}) satisfies $test
)
};
for $b in $xml2/b
where local:deep-equal-a($b, $xml1)
return $b
如果每个级别最多只有一个a
元素,则可以简化查询:
declare function local:deep-equal-a($xml, $find) {
let $xa := $xml/a, $fa := $find/a
return not($xa and $fa) or
$xa/@name = $fa/@name and local:deep-equal-a($xa, $fa)
};