views:

71

answers:

2

I have this XML in a SQL Server table:

<root>
  <meetings>
    <meeting>
      <id>111</id>
      <participants>
        <participant><name>Smith</name></participant>
        <participant><name>Jones</name></participant>
        <participant><name>Brown</name></participant>
      </participants>
    </meeting>
    <meeting>
      <id>222</id>
      <participants>
        <participant><name>White</name></participant>
        <participant><name>Bloggs</name></participant>
        <participant><name>McDonald</name></participant>
      </participants>
    </meeting>
  </meetings>
</root>

And want a result set like this:

MeetingID    Name
111          Smith
111          Jones
111          Brown
222          White
222          Bloggs
222          McDonald

This is easy using select from openxml but I failed using XQuery. Can someone help me there, and maybe also give pros and cons for either method?

+3  A: 

Once you've fixed your invalid XML (the <name> elements need to be ended with a </name> end tag), you should be able to use this:

SELECT 
    Meetings.List.value('(id)[1]', 'int') AS 'Meeting ID',
    Meeting.Participant.value('(name)[1]', 'varchar(50)') AS 'Name'
FROM
    @input.nodes('/root/meetings/meeting') AS Meetings(List)
CROSS APPLY
    Meetings.List.nodes('participants/participant') AS Meeting(Participant)

Basically, the first call to .nodes() gives you a pseudo-table of all <meeting> nodes, from which I extract the meeting ID.

The second .nodes() call on that <meeting> tag digs deeper into the <participants>/<participant> list of subnodes and extracts the name from those nodes.

marc_s
Thanks, exactly what I needed. I do find openXML syntax easier to understand though.
Graeme
@Graeme: really? I find OpenXML very unintuitive and quite messy, actually.
marc_s
Graeme
A: 

This may give you the XQuery based Table based output.

(: Assume $x is your Xml Content. so :)
let $x := Assign your Xml Content.
let $d1:= <table border="1"><tr><td>Meeting</td><td> Participant</td></tr>
  { for $p in $x//meeting/participants/participant 
              return element{'tr'} {
                    element{'td'} {$p/parent::*/parent::*/id/text()},
                    element{'td'} {data($p)}                        
                }
          }

   </table>
kadalamittai