Reputation: 6827
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
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