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>

Saxonを使用して実行されるXQueryプログラムは、次のXMLを生成します

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

$ compareDirectlyが真であると期待しますが(他の2つの例と同じ)、fn:deep-equalは直感的に期待するようには機能しないようです。これが正しい振る舞いであるかどうか疑問に思います。

2つのXMLノードを比較するためのより良い方法はありますか?

XMLスニペット(例では$docや$messageの値など)と文字列リテラルを使用するこの特殊なケースの両方に使用できる一般的なソリューションを探しています。

4

1 に答える 1

2

スペックから:

ディープイコールであるためには、ペアごとにディープイコールであるアイテムが含まれている必要があります。また、2つのアイテムが完全に等しいためには、それらは等しいと比較されるアトミック値であるか、子が深い等しい同じ名前の同じ種類のノードである必要があります。

したがって、テキストノードをアトミ​​ックタイプと比較したときにtrueが返されないのはこのためです。他の2つの例では、2つの文字列アトミックタイプを比較しています。ノードを再帰的に比較するdeep-equalは必要ないように見えます。その場合は、文字列を比較するだけです。

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

他の要件がある場合は、それらをより明確に示すために例を更新する必要がある場合があります。

于 2012-10-02T19:26:11.043 に答える