BaseX:放置多个 'replace ' 的正确语法

BaseX: correct syntax to place multiple 'replace '

declare function local:stripNS($name as xs:string?)
as xs:string?
{
  if(contains($name, ':'))
  then substring($name, functx:index-of-string($name, ':') + 1)
  else $name
};

for $x in doc("test.xml")//*[@ref]
let $tmp:=local:stripNS($x/@ref)
return replace value of node $x/@ref with $tmp

我想从 reftype 属性的值中删除命名空间。所以 <test ref='haha:123' type='hehe:456'/> 应该变成 <test ref='123' type='456'/>。我不知道正确的语法,下面是我想要的理想 .xqy 文件:

declare function local:stripNS($name as xs:string?)
as xs:string?
{
  if(contains($name, ':'))
  then substring($name, functx:index-of-string($name, ':') + 1)
  else $name
};

for $x in doc('test.xml')//*[@ref]
let $tmp:=local:stripNS($x/@ref)
return replace value of node $x/@ref with $tmp,

for $x in doc('test.xml')//*[@type]
let $tmp:=local:stripNS($x/@type)
return replace value of node $x/@ref with $tmp

但显然它包含语法错误:

[XUDY0017] Node can only be replaced once: attribute ref {"123"}.

$ basex -u test.xqy

使用上面的命令进行测试。输出将写回 test.xml.

下面的查询应该可以完成这项工作:

declare function local:stripNS($name as xs:string) as xs:string {
  replace($name, "^.*:", "")
};

for $attr in doc('test.xml')//*/(@ref, @type)
let $tmp := local:stripNS($attr)
return replace value of node $attr with $tmp

您遇到的问题是第二个 flwor 表达式中的拼写错误:您尝试两次替换同一属性。

for $x in doc('test.xml')//*[@type]
let $tmp:=local:stripNS($x/@type)
return replace value of node $x/@ref with $tmp
                             (: ^^^^ should be @type :)

无论如何,您的查询过于复杂。首先,XQuery 知道您正在重写的 substring-after($string, $token) 函数。所以你可以把你的功能缩减到

declare function local:stripNS($name as xs:string?)
as xs:string?
{
  if(contains($name, ':'))
  then substring-after($name, ':')
  else $name
};

同时删除 functx 依赖项。

此外,您还可以 select 使用单个查询的多个不同属性,将查询简化为

for $attribute in doc('test.xml')//(@ref, @type)
return replace value of node $attribute with local:stripNS($attribute)

最后,添加一个简单的where子句让你放弃整个功能(同时减少更新属性的数量,这将加快大文档的查询):

for $attribute in doc('test.xml')//(@ref, @type)
where contains($attribute, ':')
return replace value of node $attribute with substring-after($attribute, ':')