Zach Bonham
Zach Bonham

Reputation: 6827

Return rowset from Xml input

I am having a tough time struggling with XML within Sql Server 2008. I have an xml document that I need to parse into a rowset. I'm trying to come up with a sample query, that when executed against the blob, returns results such as:

ID                                   Status
--------                             -------- 
3765aaf7-afaa-4a46-8499-5a61b607692c 0
1234aaf7-afaa-4a46-8499-5a61b607692c 1

Here is the sample XML:

DECLARE @xml XML

SET @xml = '<Batch xmlns="urn:mynamespace">
  <request xmlns:b="urn:mymessages">
    <b:Batches xmlns:c="urn:myentities">
      <c:BatchEntry>
        <c:ID>3765aaf7-afaa-4a46-8499-5a61b607692c</c:ID>
        <c:Status>0</c:Status>
      </c:BatchEntry>
      <c:BatchEntry>
        <c:ID>1234aaf7-afaa-4a46-8499-5a61b607692c</c:ID>
        <c:Status>1</c:Status>
      </c:BatchEntry>
    </b:Batches>
    <b:BatchID>8492cbaa-eea5-479d-86c4-60cb62ac4b7c</b:BatchID>
  </request>
</Batch>'

The closest I've come is with:

SELECT T.a.query('.') AS ID 
FROM @xml.nodes('/*[local-name() = "Batch"]/*[local-name() = "request"]/*[local-name() = "Batches"]/*[local-name() = "BatchEntry"]/*[local-name() = "ID"]/text()') T(a)

But I cannot figure out how to basically select the 'Batches' node and then return a rowset for each 'BatchEntry'. I feel like I just don't understand some of the Sql Server xml operators just yet.. :)

Your help greatly appreciated!


UPDATE 2011-01-07

With @IanC answer below, I was able to get a complete working instance, with xml namespaces, of what I needed to do. I'm updating here just in case someone else runs across it.

DECLARE @xml XML

SET @xml = 
'<Batch xmlns="urn:mynamespace">
  <request xmlns:b="urn:mymessages">
    <b:Batches xmlns:c="urn:myentities">
      <c:BatchEntry>
        <c:ID>3765aaf7-afaa-4a46-8499-5a61b607692c</c:ID>
        <c:Status>0</c:Status>
      </c:BatchEntry>
      <c:BatchEntry>
        <c:ID>1234aaf7-afaa-4a46-8499-5a61b607692c</c:ID>
        <c:Status>1</c:Status>
      </c:BatchEntry>
    </b:Batches>
    <b:BatchID>8492cbaa-eea5-479d-86c4-60cb62ac4b7c</b:BatchID>
  </request>
</Batch>'

DECLARE @sp int
DECLARE @hxml int
DECLARE @Result int

DECLARE @t table 
(
    ID UNIQUEIDENTIFIER,
    BatchStatus INT   
)

EXEC    @sp = sp_xml_preparedocument @hxml OUTPUT, @xml
,
'<Batch 
    xmlns:a="urn:mynamespace"
    xmlns:b="urn:mymessages"
    xmlns:c="urn:myentities"
/>'

if @sp != 0 begin
    SET @Result = '0'
    RETURN
end

INSERT INTO @t
SELECT *
FROM OPENXML (@hxml, '/a:Batch/a:request/b:Batches/c:BatchEntry', 2)
WITH
(
    ID          UNIQUEIDENTIFIER    'c:ID',
    BatchStatus INT                 'c:Status'
)

SELECT * FROM @t

EXEC    sp_xml_removedocument @hxml;

Upvotes: 2

Views: 817

Answers (1)

IamIC
IamIC

Reputation: 18249

Try this as a general pattern. If you need more help with it, let me know and I'll tailor it to your XML.

DECLARE @t table (
    ProductTypeID   int,
    LowMin          real,
    HiMax           real,
    ParamTypeID     int,
    ParamWeight     real,
    Low             real,
    Hi              real,
    Mode            tinyint         
)

EXEC    @sp = sp_xml_preparedocument @hxml OUTPUT, @XMLText

if @sp != 0 begin
    SET @Result = '0'
    RETURN
end

INSERT INTO @t
SELECT      *
FROM        OPENXML (@hxml, '/query/product/param/item', 2)
WITH        (
            ProductTypeID   int     '../../@type',
            LowMin          real    '../@lowMin',
            HiMax           real    '../@hiMax',
            ParamTypeID     int     '../@type',
            ParamWeight     real    '@weight',
            Low             real    '@low',
            Hi              real    '@hi',
            Mode            tinyint '@mode'
            )

EXEC    sp_xml_removedocument @hxml;

Upvotes: 2

Related Questions