0

我正在尝试使用 XQuery 函数fn:deep-equal来比较 XML 文档的各个部分,但我遇到了意外的行为。将 XPath 值与字符串文字进行比较时,函数返回 false。

例如下面的代码

let $doc :=
  <root>
    <child><message>Hello</message></child>
  </root>

let $message := <message>Hello</message>

let $value := $doc/child/message/text()
let $compareDirectly := fn:deep-equal($value, "Hello") (: -> false :)
let $compareAsString := fn:deep-equal(fn:concat($value, ""), "Hello") (: -> true :)
let $comparePath := fn:deep-equal($value, $message/text()) (: -> true :)

return
  <results>
    <value>{$value}</value>
    <directly>{$compareDirectly}</directly>
    <asString>{$compareAsString}</asString>
    <path>{$comparePath}</path>
  </results>

XQuery 程序使用 Saxon 执行,生成以下 XML

<?xml version="1.0" encoding="UTF-8"?>
<results>
    <value>Hello</value>
    <directly>false</directly>
    <asString>true</asString>
    <path>true</path>
</results>

我希望 $compareDirectly 为真(与其他两个示例相同),但 fn:deep-equal 似乎不像我直觉预期的那样工作。我想知道这是否是正确的行为。

有没有更好的哇如何比较两个 XML 节点?

我正在寻找一些通用的解决方案,它既可用于 XML 片段(例如 $doc 或 $message 的值),也可用于字符串文字的这种特殊情况。

4

1 回答 1

2

规格

要深度相等,它们必须包含成对深度相等的项目;并且要使两个项目深度相等,它们必须是比较相等的原子值,或者是具有相同名称的同类节点,其子节点是深度相等的。

所以这就是为什么在将文本节点与原子类型进行比较时它不返回 true 的原因。在您的其他两个示例中,您正在比较 2 个字符串原子类型。看起来你不需要 deep-equal,它递归地比较节点。如果是这种情况,那么您可以只比较字符串:

$doc/child/message/string() eq $message/string()
=> true()

如果还有其他要求,那么您可能需要更新您的示例以更清楚地展示这些要求。

于 2012-10-02T19:26:11.043 回答