2016-06-11 2 views
0
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 

Я хочу, чтобы лишить имена от значения ref и type атрибута. SO <test ref='haha:123' type='hehe:456'/> должно стать <test ref='123' type='456'/>. Я не знаю, правильный синтаксис, ниже идеальный .xqy файл Я хочу:Basex: правильный синтаксис, чтобы разместить несколько «заменить»

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.

+0

Пожалуйста, всегда указывайте пример ввода. Делает жизнь проще для тех, кто отвечает на вопросы, и дает ответы, лучше отвечающие вашей реальной проблеме взамен. –

+0

@JensErat У вас уже есть это. Просто скопируйте и вставьте '' в локальный файл с именем 'test.xml' –

+0

Действительно. Еще одна важная вещь, которую вы пропустили: ** всегда ** включайте сообщение об ошибке, если вы его получите. Если бы вы отправили сообщение об ошибке, возможно, большинство пользователей XQuery здесь заметили бы проблему сразу, даже не скопировав код. –

ответ

1

Проблема у Вас есть опечатка во втором выражении 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.

Кроме того, вы также можете выбрать несколько различных атрибутов с помощью одного запроса, упрощая запрос

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, ':') 
0

Следующий запрос должен делать эту работу:

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 
Смежные вопросы