views:

300

answers:

2

How can I get the second column with the same column name using OPENXML in MSSQL 2005?

Here is the result set that I plan to get.

columnData1 columnData2

A B

C D

E F

DECLARE @hDoc int, @xmldata varchar(max)
SELECT @xmldata = 

'<?xml version="1.0" encoding="utf-8" ?>
<reportResponse>
<reportDataRow rowNum="1">
<columnData colNum="1">
  <data>A</data>
</columnData>
<columnData colNum="2">
  <data>B</data>
</columnData>
</reportDataRow>
<reportDataRow rowNum="2">
<columnData colNum="1">
  <data>C</data>
</columnData>
<columnData colNum="2">
  <data>D</data>
</columnData>
</reportDataRow>
<reportDataRow rowNum="3">
<columnData colNum="1">
  <data>E</data>
</columnData>
<columnData colNum="2">
  <data>F</data>
</columnData>
</reportDataRow>
</reportResponse>'

EXEC sp_xml_preparedocument @hDoc OUTPUT, @xmldata

SELECT *
FROM OPENXML(@hDoc, '/reportResponse/reportDataRow',2)
WITH (columnData varchar(50) , columnData2 varchar(50) )


SELECT *
FROM OPENXML(@hDoc, '/reportResponse/reportDataRow/columnData',2)
WITH (data varchar(50))

EXEC sp_xml_removedocument @hDoc
A: 

I don't think this is possible without using OPENXML as an interim rowset:

DECLARE @hDoc INT, @xmldata VARCHAR(MAX)
SELECT @xmldata = 

'<?xml version="1.0" encoding="utf-8" ?>
<reportResponse>
<reportDataRow rowNum="1">
<columnData colNum="1">
  <data>A</data>
</columnData>
<columnData colNum="2">
  <data>B</data>
</columnData>
</reportDataRow>
<reportDataRow rowNum="2">
<columnData colNum="1">
  <data>C</data>
</columnData>
<columnData colNum="2">
  <data>D</data>
</columnData>
</reportDataRow>
<reportDataRow rowNum="3">
<columnData colNum="1">
  <data>E</data>
</columnData>
<columnData colNum="2">
  <data>F</data>
</columnData>
</reportDataRow>
</reportResponse>'

EXEC sp_xml_preparedocument @hDoc OUTPUT, @xmldata

;WITH xmlCTE
AS
(
        SELECT *
        FROM OPENXML(@hDoc, '/reportResponse/reportDataRow/columnData',2)
        WITH (DATA VARCHAR(50) 
             ,rowNum INT       '../@rowNum'
             ,colNum INT       '@colNum')
)
SELECT c1.DATA AS columnData1
       ,c2.DATA AS columnData2
FROM xmlCTE AS c1
JOIN xmlCTE AS c2
ON   c1.rowNum = c2.rowNum
AND  c2.colNum = 2
WHERE c1.colNum = 1

EXEC sp_xml_removedocument @hDoc
Ed Harper
A: 

Thanks. I found the answer by using PIVOT. In my real case, I have more than 10 columns and thousands of rows, so it won't be easy to self join. BTW, this is for parsing xml data set from PayPal reportEngineResponse. Here is the answer to share.

DECLARE @hDoc INT, @xmldata VARCHAR(MAX)
SELECT @xmldata = 

'<?xml version="1.0" encoding="utf-8" ?>
<reportResponse>
<reportDataRow rowNum="1">
<columnData colNum="1">
  <data>A</data>
</columnData>
<columnData colNum="2">
  <data>B</data>
</columnData>
</reportDataRow>
<reportDataRow rowNum="2">
<columnData colNum="1">
<data>C</data>
</columnData>
<columnData colNum="2">
<data>D</data>
</columnData>
</reportDataRow>
<reportDataRow rowNum="3">
<columnData colNum="1">
<data>E</data>
</columnData>
<columnData colNum="2">
<data>F</data>
</columnData>
</reportDataRow>
</reportResponse>'

EXEC sp_xml_preparedocument @hDoc OUTPUT, @xmldata

SELECT [1] as row1, [2] as row2
FROM
(SELECT *
FROM OPENXML(@hDoc, '/reportResponse/reportDataRow/columnData',2)
WITH (data VARCHAR(50) 
 ,rowNum INT       '../@rowNum'
 ,colNum INT       '@colNum')) P
PIVOT
(
MAX(data)
FOR colNum IN ([1],[2]) 
)AS pvt

EXEC sp_xml_removedocument @hDoc
Vincent