用于导航以 XML 编码的图形结构的 XPath
XPath to navigate graph structure encoded in XML
我有一个用 XML 编码的图形结构。有向无环图,准确的说。
节点是唯一标识的,并且具有编码的后继关系。
是否可以构造一个 XQuery 或 XPath 函数来导航图形以找到满足简单条件的第一个节点?
更准确地说,我们来看下面的XML文档:
<?xml version="1.0" encoding="UTF-8"?>
<doc>
<obj>
<id>1</id>
<name>FINDME</name>
<relations>
<successor>2</successor>
</relations>
</obj>
<obj>
<id>2</id>
<relations>
<predecessor>1</predecessor>
<successor>3</successor>
</relations>
</obj>
<obj>
<id>3</id>
<relations>
<predecessor>2</predecessor>
</relations>
</obj>
</doc>
假设,当前节点是3。
我想找到一个前任节点的 id,它的名称标签等于 "FINDME"。
为此,我可以使用以下 XPath:
/doc/obj[name='FINDME'
and id=/doc/obj[
id=/doc/obj[
id=3
]/relations/predecessor
]/relations/predecessor
]/id
是否可以概括查询以处理任意级别的关系?
编辑:joemfb 回答确实回答了这个问题。我有一个额外的请求,它可以处理一个节点的多个前任并且 return 任何节点不超过一次吗?
因此,它也适用于以下示例:
<?xml version="1.0" encoding="UTF-8"?>
<doc>
<obj>
<id>1</id>
<name>FINDME</name>
<relations>
<successor>2</successor>
<successor>4</successor>
</relations>
</obj>
<obj>
<id>4</id>
<relations>
<successor>2</successor>
<predecessor>1</predecessor>
</relations>
</obj>
<obj>
<id>2</id>
<relations>
<predecessor>1</predecessor>
<predecessor>4</predecessor>
<successor>3</successor>
</relations>
</obj>
<obj>
<id>3</id>
<relations>
<predecessor>2</predecessor>
</relations>
</obj>
</doc>
如果我没看错你的需求,你想找到前辈的前辈,只要他们存在。这是递归函数的完美应用。
这是一个 XQuery 解决方案:
xquery version "1.0";
declare function local:predecessors($doc, $node)
{
let $immediate-predecessor := $doc/doc/obj[id = $node/relations/predecessor]
return
if (fn:exists($immediate-predecessor))
then (
$immediate-predecessor,
local:predecessors($doc, $immediate-predecessor)
)
else ()
};
let $doc := document { (: your doc ... :) }
let $results := local:predecessors($doc, $doc/doc/obj[id eq "3"])
return element results { $results intersect $results }
更新:
为了支持多个 predecessor
元素,谓词 [id = $node/relations/predecessor]
需要通用比较运算符 =
,它支持任一操作数中的序列,而不是值比较运算符 [=15] =].
对于 return 个不同的节点,我们可以使用 intersect
operator,其中 return 是两个操作数共有的唯一节点序列(我也可以使用 union
类似地 returns 唯一节点)。
我已经在 Saxon HE 中测试了这些变化:
java -cp /usr/local/Cellar/saxon/9.5.1.6/libexec/saxon9he.jar \
net.sf.saxon.Query -q:test.xq | xmllint --format -
我有一个用 XML 编码的图形结构。有向无环图,准确的说。 节点是唯一标识的,并且具有编码的后继关系。
是否可以构造一个 XQuery 或 XPath 函数来导航图形以找到满足简单条件的第一个节点?
更准确地说,我们来看下面的XML文档:
<?xml version="1.0" encoding="UTF-8"?>
<doc>
<obj>
<id>1</id>
<name>FINDME</name>
<relations>
<successor>2</successor>
</relations>
</obj>
<obj>
<id>2</id>
<relations>
<predecessor>1</predecessor>
<successor>3</successor>
</relations>
</obj>
<obj>
<id>3</id>
<relations>
<predecessor>2</predecessor>
</relations>
</obj>
</doc>
假设,当前节点是3。 我想找到一个前任节点的 id,它的名称标签等于 "FINDME"。 为此,我可以使用以下 XPath:
/doc/obj[name='FINDME'
and id=/doc/obj[
id=/doc/obj[
id=3
]/relations/predecessor
]/relations/predecessor
]/id
是否可以概括查询以处理任意级别的关系?
编辑:joemfb 回答确实回答了这个问题。我有一个额外的请求,它可以处理一个节点的多个前任并且 return 任何节点不超过一次吗?
因此,它也适用于以下示例:
<?xml version="1.0" encoding="UTF-8"?>
<doc>
<obj>
<id>1</id>
<name>FINDME</name>
<relations>
<successor>2</successor>
<successor>4</successor>
</relations>
</obj>
<obj>
<id>4</id>
<relations>
<successor>2</successor>
<predecessor>1</predecessor>
</relations>
</obj>
<obj>
<id>2</id>
<relations>
<predecessor>1</predecessor>
<predecessor>4</predecessor>
<successor>3</successor>
</relations>
</obj>
<obj>
<id>3</id>
<relations>
<predecessor>2</predecessor>
</relations>
</obj>
</doc>
如果我没看错你的需求,你想找到前辈的前辈,只要他们存在。这是递归函数的完美应用。
这是一个 XQuery 解决方案:
xquery version "1.0";
declare function local:predecessors($doc, $node)
{
let $immediate-predecessor := $doc/doc/obj[id = $node/relations/predecessor]
return
if (fn:exists($immediate-predecessor))
then (
$immediate-predecessor,
local:predecessors($doc, $immediate-predecessor)
)
else ()
};
let $doc := document { (: your doc ... :) }
let $results := local:predecessors($doc, $doc/doc/obj[id eq "3"])
return element results { $results intersect $results }
更新:
为了支持多个 predecessor
元素,谓词 [id = $node/relations/predecessor]
需要通用比较运算符 =
,它支持任一操作数中的序列,而不是值比较运算符 [=15] =].
对于 return 个不同的节点,我们可以使用 intersect
operator,其中 return 是两个操作数共有的唯一节点序列(我也可以使用 union
类似地 returns 唯一节点)。
我已经在 Saxon HE 中测试了这些变化:
java -cp /usr/local/Cellar/saxon/9.5.1.6/libexec/saxon9he.jar \
net.sf.saxon.Query -q:test.xq | xmllint --format -