我有一个查询,它附加了@xml:ids中元素的唯一引用。它应该工作,但我怎么能避免函数local的重复:add-references()?
xquery version "3.0";
declare namespace tei="http://www.tei-c.org/ns/1.0";
declare function local:change-attributes($node as node(), $new-name as xs:string, $new-content as item(), $action as xs:string, $target-element-names as xs:string+, $target-attribute-names as xs:string+) as node()+ {
if ($node instance of element())
then
element {node-name($node)}
{
if ($action = 'attach-attribute-to-element' and name($node) = $target-element-names)
then ($node/@*, attribute {$new-name} {$new-content})
else
$node/@*
,
for $child in $node/node()
return $child
}
else $node
};
declare function local:add-references($element as element()) as element() {
element {node-name($element)}
{$element/@*,
for $child in $element/node()
return
if ($child instance of element() and $child/../@xml:id)
then
if (not($child/@xml:id))
then
let $local-name := local-name($child)
let $preceding-siblings := $child/preceding-sibling::element()
let $preceding-siblings := count($preceding-siblings[local-name(.) eq $local-name])
let $following-siblings := $child/following-sibling::element()
let $following-siblings := count($following-siblings[local-name(.) eq $local-name])
let $seq-no :=
if ($preceding-siblings = 0 and $following-siblings = 0)
then ''
else $preceding-siblings + 1
let $id-value := concat($child/../@xml:id, '-', $local-name, if ($seq-no) then '-' else '', $seq-no)
return
local:change-attributes($child, 'xml:id', $id-value, 'attach-attribute-to-element', ('body', 'quote', 'titlePage','text','p','div','front','head','titlePart'), '')
else local:add-references($child)
else
if ($child instance of element())
then local:add-references($child)
else $child
}
};
let $doc :=
<TEI xmlns="http://www.tei-c.org/ns/1.0">
<text xml:id="hamlet">
<front>
<div>
<p>…</p>
</div>
<titlePage>
<titlePart>…</titlePart>
</titlePage>
<div>
<p>…</p>
</div>
</front>
<body>
<p>…</p>
<quote>…</quote>
<p>…</p>
<div>
<head>…</head>
<p>…</p>
<quote>…</quote>
<p>…</p>
<p>…</p>
</div>
<div>
<lg>
<l>…</l>
<l>…</l>
</lg>
</div>
</body>
</text>
</TEI>
return local:add-references(local:add-references(local:add-references(local:add-references(local:add-references($doc)))))
必须有一些方法以递归方式调用函数,使用文档的深度将其自身包装一定次数。
问题是元素的某个深度必须等到它们的父元素被赋予@xml:ids才能获得它们自己(顶层必须用@xml:id播种)。
答案 0 :(得分:2)
这可能不是最佳解决方案,但您可能只是测试应用该函数是否仍会更改任何内容,否则取消:
declare function local:add-references-recursively($now as element()) as element() {
let $next := local:add-references($now)
return
if (deep-equal($now, $next))
then $now
else local:add-references-recursively($next)
};
使用
致电local:add-references-recursively($doc)