Reputation: 31
I am trying to select the dates from the following XML:
<output xmlns="http://www.abcde.com/pqwlv/dwh" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="46177" xsi:schemaLocation="dwhOutput.xsd">
<parameter>
<isCoupon>0</isCoupon>
</parameter>
<schedule>
<executionDate businessDay="2020-01-09">2020-01-09</executionDate>
<endDates>
<item businessDay="2019-03-18">2019-03-17</item>
<item businessDay="2019-06-17">2019-06-17</item>
<item businessDay="2019-09-17">2019-09-17</item>
<item businessDay="2019-12-17">2019-12-17</item>
<item businessDay="2020-03-17">2020-03-17</item>
<item businessDay="2020-06-17">2020-06-17</item>
</endDates>
</schedule>
</output>
And I want to select the dates list ("businessDay") from "endDates" field, So the output will be (as a table):
endDates
----------
2019-03-18
2019-06-17
2019-09-17
2019-12-17
2020-03-17
2020-06-17
I have tried to use this query:
SELECT endDates.query('.') AS endDates
FROM [table]
CROSS APPLY
OUTPUT.nodes('declare namespace ns="http://www.abcde.com/pqwlv/dwh"; /ns:output/ns:schedule/ns:endDates') AS T1(endDates)
And got:
<p1:endDates xmlns:p1="http://www.abcde.com/pqwlv/dwh">
<p1:item businessDay="2019-03-18">2019-03-17</p1:item>
<p1:item businessDay="2019-06-17">2019-06-17</p1:item>
<p1:item businessDay="2019-09-17">2019-09-17</p1:item>
<p1:item businessDay="2019-12-17">2019-12-17</p1:item>
<p1:item businessDay="2020-03-17">2020-03-17</p1:item>
<p1:item businessDay="2020-06-17">2020-06-17</p1:item>
</p1:endDates>
How can I dig deeper and select the dates?
Upvotes: 3
Views: 44
Reputation: 22157
It seems here is the fastest and clean method. No need to declare the xsi namespace because it is not used.
SQL
-- DDL and sample data population, start
DECLARE @tbl TABLE (ID INT IDENTITY(1,1) PRIMARY KEY, xml_data XML);
INSERT INTO @tbl
VALUES (N'<output xmlns="http://www.abcde.com/pqwlv/dwh" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
id="46177" xsi:schemaLocation="dwhOutput.xsd">
<parameter>
<isCoupon>0</isCoupon>
</parameter>
<schedule>
<executionDate businessDay="2020-01-09">2020-01-09</executionDate>
<endDates>
<item businessDay="2019-03-18">2019-03-17</item>
<item businessDay="2019-06-17">2019-06-17</item>
<item businessDay="2019-09-17">2019-09-17</item>
<item businessDay="2019-12-17">2019-12-17</item>
<item businessDay="2020-03-17">2020-03-17</item>
<item businessDay="2020-06-17">2020-06-17</item>
</endDates>
</schedule>
</output>');
-- DDL and sample data population, end
;WITH XMLNAMESPACES(DEFAULT 'http://www.abcde.com/pqwlv/dwh')
SELECT ID
, col.value('.','DATE') AS endDates
FROM @tbl AS tbl
CROSS APPLY tbl.xml_data.nodes('/output/schedule/endDates/item/@businessDay') AS tab(col);
Output
+----+------------+
| ID | endDates |
+----+------------+
| 1 | 2019-03-18 |
| 1 | 2019-06-17 |
| 1 | 2019-09-17 |
| 1 | 2019-12-17 |
| 1 | 2020-03-17 |
| 1 | 2020-06-17 |
+----+------------+
Upvotes: 0
Reputation: 5110
You are close to your desired output.
SELECT T1.endDates.value('@businessDay','DATE')
FROM(
SELECT @X AS COL
)A
CROSS APPLY
A.COL.nodes('declare namespace ns="http://www.abcde.com/pqwlv/dwh";
/ns:output/ns:schedule/ns:endDates/ns:item') AS T1(endDates)
Output:
(No column name)
2019-03-18
2019-06-17
2019-09-17
2019-12-17
2020-03-17
2020-06-17
Upvotes: 0
Reputation: 95544
You weren't far off. You need to use WITH XMLNAMESPACES
at the start of your query, to define the namespace, and then you can transverse the nodes in the FROM
:
DECLARE @xml xml = '<output xmlns="http://www.abcde.com/pqwlv/dwh" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="46177" xsi:schemaLocation="dwhOutput.xsd">
<parameter>
<isCoupon>0</isCoupon>
</parameter>
<schedule>
<executionDate businessDay="2020-01-09">2020-01-09</executionDate>
<endDates>
<item businessDay="2019-03-18">2019-03-17</item>
<item businessDay="2019-06-17">2019-06-17</item>
<item businessDay="2019-09-17">2019-09-17</item>
<item businessDay="2019-12-17">2019-12-17</item>
<item businessDay="2020-03-17">2020-03-17</item>
<item businessDay="2020-06-17">2020-06-17</item>
</endDates>
</schedule>
</output>';
WITH XMLNAMESPACES(DEFAULT 'http://www.abcde.com/pqwlv/dwh',
'http://www.w3.org/2001/XMLSchema-instance' AS xsi)
SELECT eD.item.value('@businessDay','date') AS endDate
FROM (VALUES(@XML))V(YourXML) --This would be your table
CROSS APPLY V.YourXML.nodes('/output/schedule/endDates/item') eD(item);
Upvotes: 1