Yahya Uddin
Yahya Uddin

Reputation: 28841

XQuery - How to insert elements?

I have the following xml:

<subjects>
   <subject id="5" name="Maths"/>
   <subject id="10" name="English" points="5"/>
   <subject id="15" name="Science" points="10" cats="15"/>
</subjects>

and I have the following code:

for $subject in $subjects/subject
return 
     <subject id="{$subject/@id}">
          <foo/>
     </subject>

which outputs

<subject id="5"><foo/></subject>
<subject id="10"><foo/></subject>
<subject id="15"><foo/></subject>

However the above code does not show all the attributes of subject. Only id. Of course I can continue hardcoding more attributes but this won't help if I don't know what the attributes names are.

What I want is something like this:

<subject id="5" name="Maths"><foo/></subject>
<subject id="10" name="English" points="5"><foo/></subject>
<subject id="15" name="Science" points="10" cats="15"><foo/></subject>

I believe the solution would be something like this:

for $subject in $subjects/subject
return 
     insert-child( <foo/>, $subject)

How do I do this?

Upvotes: 0

Views: 216

Answers (2)

Michael Kay
Michael Kay

Reputation: 163262

Once your XML source becomes more complicated, if your task is to make small changes to a large XML document then I would strongly recommend using XSLT rather than XQuery. XSLT's recursive-descent processing model based on matching template rules is absolutely cut out for this task, and if you try to do it in XQuery you end up replicating this mechanism "by hand" in your own recursive functions.

An alternative is XQuery Update (which, to answer your question, is supported in commercial editions of Saxon). I'm no great enthusiast of XQuery Update, except perhaps in a database context, but it does the job and some people like it.

Upvotes: 2

wst
wst

Reputation: 11773

You were on the right track. As you are rewriting the elements, you can simply use a wildcard attribute selector to copy all of the attributes from the context node to your newly constructed element.

for $subject in $subjects/subject
return 
  <subject>{
      $subject/@*,
      <foo/>
  }</subject>

Upvotes: 1

Related Questions