Question

Below is the XML structure. Its a specimen of my original structure, not the exact.

<Docs>
  <Doc>
   <Para>
      <P n="1"><B>Constants : T</B>he value of pi is 3.14</P>
      <P n="2">pi is a geometric term.</P>
   </Para>
  </Doc>
  <Doc>
   <Para>
     <P n="1"><B>Constants : T</B>he value of g is 9.81 m/sqr of sec</P>
     <P n="2">g is a acceleration due to gravity.</P>
   </Para>
  </Doc>
  <Doc>
    <Para>
      <P n="1"><B>Constants : T</B>he value of c is 3.00 x 10 power 8 m/sec</P>
      <P n="2">c is a speed of light in vacuum.</P>
    </Para>
  </Doc>
</Docs>

I have generated XML files programmatically. The B node has data Constant : T, where as it should be only Constants :. I have written an XQuery to do the necessary changes, but its not working as expected.

below is the XQuery - Version 1

for $x in doc('doc1')//Doc
where $x/Para/P[@n="1"]/B/text()="Constants : T"

return
let $p := $x/Para/P[@n="1"]
let $pText := concat("T", $p/text())
let $tag := <P n="1">{$pText}</P>

return
(
delete node $p,
insert node $tag as first into $x/Para,
insert node <B>Constants :</B> as first into $x/Para/P[@n="1"]  
)

Version - 2 (Smaller, sweeter but not working !!!)

let $b := <B> Constants :</B>
for $x in doc('doc1')//Doc/Para[P[@n="1"]/B/text()="Constants : T"]/P[@n="1"]

return
(
 replace value of node $x with concat("T", $x/text()),
 insert node $b/node() as first into $x
)

Neither query is inserting <B>Constants : </B>. Can anybody help me on this?

Was it helpful?

Solution

The problem you are facing has to do with he nature of XQuery Updates. It uses a pending update list and applies all updates at the end of the query. The order of the update operation is well defined and is therefore independent from the order you give in your update statement. See some more information at https://docs.basex.org/wiki/Updates#Pending_Update_List.

So in your case, insert is applied before replace, so you are actually replacing your just already inserted node and thus overwrite this change.

To resolve this, I would just replace the text values and replace the B node. Therefore, both of your operations are independent from another and their order of execution can be changed without a problem.

let $b := <B> Constants :</B>
for $x in doc('doc1')//Doc/Para[P[@n="1"]/B/text()="Constants : T"]/P[@n="1"]

return
(
    replace value of node $x/text() with concat("T", $x/text()),
    replace node $x/B with $b
)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top