4

I have a xml document like

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

How to convert this document with all nodes, that means if a node contains text and child node convert text into a child node (let's say childtext) using xquery-update

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

And here is what I tried:

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

I could not delete the text which has sibling node.

Prakash Thapa
  • 1,285
  • 14
  • 27
  • first I can create node "childtext" with value text(). Now I have to delete the old text that still there> I cannot delete this only this text. if I want to make value empty other child node will be also removed. – Prakash Thapa Jan 13 '14 at 10:05
  • Here what I tried to do: let $a := .... return copy $i := $a modify ( for $x in $i/descendant-or-self::* return ( if($x/text() and exists($x/*)) then ( insert node {$x/text()} as first into $x, (: here should somehow delete the this text or update to next level:) ) else ( ) ) ) return $i – Prakash Thapa Jan 13 '14 at 10:14
  • Please edit this code to your question (its hardly readable here) and do not omit parts of code so it is not running any more (`let $a := ....` is no working code for sure). What problems do you have with your current code? – Jens Erat Jan 13 '14 at 10:17
  • Done!! please check question once again – Prakash Thapa Jan 13 '14 at 10:36
  • @dirkk: If there is a problem with a post, please describe the problem in detail, instead of just posting "what have you tried". See [this Meta post](http://meta.stackexchange.com/a/172760/152134) on whether "what have you tried" comments are acceptable and alternatives to "what have you tried". Thanks! – Qantas 94 Heavy Jan 25 '14 at 08:01
  • @Qantas94Heavy I honestly don't know what I should have asked instead in this case. The XQuery code was missing and as a result of my comment the OP gave this information and as you can see in answered the question. So in fact I think it was quite helpful and every other thing I could have asked would have been just a variation in speech, e.g. "Please show us some code" or "Did you already try something with XQuery". So what would have been a more helpful version of my comment, in this particular case? – dirkk Jan 25 '14 at 16:49

2 Answers2

3

As you want to replace an element, you should simply use the replace construct, instead of inserting the new element and deleting the old one. Seems much simpler to me:

copy $i := $a
modify (
  for $x in $i/descendant-or-self::*[exists(*)]/text()
  return replace node $x with <childtext>{$x}</childtext>
)
return $i
dirkk
  • 6,160
  • 5
  • 33
  • 51
  • Yes Yes Yes, that's what I really wanted :-) Thanks @dirkk :-) – Prakash Thapa Jan 13 '14 at 11:49
  • Hi Dirkk It works for just one text(). that means it will not work something like ab ab. How to solve it. – Prakash Thapa Jan 13 '14 at 13:21
  • 1
    @PrakashThapa I edited my answer, although I did saw your solution. My updated answer is in general nicer as before (putting the conditions directly as predicate into the `for` statement) and also respects multiple `text()` elements this way. I would very much prefer this solution, at is is easier readable and also more performant. – dirkk Jan 13 '14 at 14:13
0

The modified solution is from @dirkk here:

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

Thank you Once again.

Prakash Thapa
  • 1,285
  • 14
  • 27