2014-01-13 1 views
4

У меня есть XML-документ, какКак преобразовать текст внутри узла в дочерний узел с помощью обновления xquery?

<root> 
    <first> 
    First Level 
    <second> 
     second level 
     <third> 
     Third Level 
     </third> 
    </second> 
    <second2> 
     another second level 
    </second2> 
    </first> 
</root> 

Как преобразовать этот документ со всеми узлами, это означает, что если узел содержит text и child node преобразовать текст в дочерний узел (скажем childtext) с помощью XQuery-обновления

<root> 
    <first> 
    <childtext>First Level</childtext> 
    <second> 
     <childtext>second level</childtext> 
     <third> 
     Third Level 
     </third> 
    </second> 
    <second2> 
     another second level 
    </second2> 
    </first> 
</root> 

А вот то, что я пробовал:

let $a := 
<root> 
    <first> 
    First Level 
    <second> 
     second level 
     <third> 
     Third Level 
     </third> 
    </second> 
    <second2> 
     another second level 
    </second2> 
    </first> 
</root> 
return 
copy $i := $a 
modify (
    for $x in $i/descendant-or-self::* 
    return (
    if($x/text() and exists($x/*)) then (
     insert node <childtext> 
     {$x/text()} 
     </childtext> as first into $x 
     (: here should be some code to delete the text only:) 
    ) else() 
) 
) 
return $i 

Я не смог удалить текст с узлом сестры.

+0

Сначала я могу создать узел «childtext» со значением text(). Теперь я должен удалить старый текст, который все еще существует> Я не могу удалить этот только этот текст. если я хочу сделать значение пустым, другой дочерний узел также будет удален. –

+0

Вот что я пытался сделать: пусть $ а: = .... возвращение копия $ я: = $ а изменения ( за $ х в $ I/потомок-или-я :: * возврата ( если ($ х/текст() и существует ($ х/*)), а затем ( вставки узла {$ х/текст()} , как первый в $ х, (: здесь надо как-то удалить этот текст или обновление на следующий уровень :) ) еще ( ) ) ) вернуть $ я –

+0

Пожалуйста, измените этот код на свой вопрос (его га rdly читаемый здесь) и не пропускайте части кода, чтобы он больше не запускался ('let $ a: = ....' не является рабочим кодом для уверенности). Какие проблемы у вас есть с вашим текущим кодом? –

ответ

3

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

copy $i := $a 
modify (
    for $x in $i/descendant-or-self::*[exists(*)]/text() 
    return replace node $x with <childtext>{$x}</childtext> 
) 
return $i 
+0

Да Да Да, это то, что я действительно хотел :-) Спасибо @dirkk :-) –

+0

Hi Dirkk Он работает только для одного текста(). это означает, что он не будет работать так, как ab ab. Как это решить. –

+1

@PrakashThapa Я отредактировал свой ответ, хотя я видел ваше решение. Мой обновленный ответ в целом лучше, чем раньше (включение условий непосредственно в качестве предиката в оператор 'for'), а также уважает несколько элементов' text() 'таким образом.Я бы очень предпочел это решение, он легче читается, а также более совершенен. – dirkk

0

Модифицированный раствор из @dirkk здесь:

copy $i := $a 
modify (
    for $x in $i/descendant-or-self::* 
    return (
    if($x/text() and exists($x/*)) then (
     if(count($x/text())=1) then (
     replace node $x/text() with <child> {$x/text()}</child> 
    ) else (
     for $j at $pos in 1 to count($x/text()) 
     return 
     replace node $x/text()[$pos] with <child>{$x/text()[$pos]}</child> 

    ) 


    ) else() 
) 
) 
return $i 

Еще раз большое спасибо.