Get list of xml from parent xml in sql - sql

Need to get the list of xml present inside an xml. This is what I have tried.
DECLARE #xml xml
SET #xml = '<a><b /><c><d /><d /><d /></c></a>';
DECLARE #i_xml xml = #xml.value('(/a/b/c)[1]', 'VARCHAR(100)')
Select #i_xml
But this gives me NULL

Based on your sample xml, c and b are on same child record of <a>. value() will give a scalar result, use query() instead.
DECLARE #xml xml
SET #xml = '<a><b /><c><d /><d /><d /></c></a>';
DECLARE #i_xml xml = #xml.query('(//a/c/child::*)')
SELECT #i_xml

Related

NameSpaces in xml sql

How can I declare the namespaces in a query?
I get an error when declaring the namespaces
Declare #Mydoc xml
set #Mydoc = (
select importe, algo,XD,
(select impuesto,tasa,transferencia
from CfdiDet
for xml raw('cfdi_detalle'),type)
from cfdienc
for xml raw('cfdi_encabezado'),type)
This is the part where I have a problem
set #Mydoc.modify('declare xmlnamespaces ('uri',cfdi')
I want to replace the "_" with ":"
The namespace prefixes are not just a part of string you could manipulate with a .modify()... Well, you could convert the XML to string, do a REPLACE and convert it back to XML. But the proper way is to declare the namespace.
To declare a namespace you can either use WITH XMLNAMESPACES or use an implicit namespace declaration (not possible in your case).
Try this
DECLARE #Mydoc XML;
WITH XMLNAMESPACES('uri' AS cfdi)
SELECT #Mydoc=
(
SELECT 'SomeDummy' AS importe
FOR XML RAW('cfdi:encabezado'),TYPE
);
SELECT #Mydoc
The result
<cfdi:encabezado xmlns:cfdi="uri" importe="SomeDummy" />

How to remove an <i> tag with a certain value from XML List through SQL Statement (Microsoft SQL Server Management Studio)

I have a simple XML List, which looks like this:
<i>8</i>
<i>20</i>
<i>24</i>
For this example I want to remove the 2nd Node from this List.
How do I do that?
DECLARE #xml XML;
SET #xml = <i>8</i><i>20</i><i>24</i>
SELECT #xml.modify('delete <i>20</i>')
Thank you!
Removes nodes from the xml where text equals value of 20:
DECLARE #xml XML = '<i>8</i><i>20</i><i>24</i>';
SET #xml.modify('delete i[text()="20"]')
select #xml;
Removes the 2nd "i" node in the XML:
DECLARE #xml XML = '<i>8</i><i>20</i><i>24</i>';
SET #xml.modify('delete i[2]')
select #xml;
Bonus: Removes nodes from the xml where text contains a value of 20:
DECLARE #xml XML = '<i>8</i><i>20 </i><i>24</i>';
SET #xml.modify('delete i[text()][contains(.,"20")]')
select #xml;
Try it like this
DECLARE #xml XML;
SET #xml = N'<i>8</i><i>20</i><i>24</i>';
DECLARE #pos INT=2;
SET #xml.modify('delete /i[sql:variable("#pos")][1]');
SELECT #xml;

accessing value from SQL parameter to use it for an XML attribute

I am trying to build an xml by using the parameter value for the attribute.
Declare #price int =100
Declare #xml xml = '<Product DiscountPrice= "{sql:variable("#price")}" />'
Select #xml
I get the following error.
Msg 9410, Level 16, State 1,
XML parsing: whitespace expected'
What am I missing here?
I believe sql:variable is only used within .query() calls. This is how you can create a snippet of xml using your variable:
Declare #price int =100
declare #xml xml;
set #xml = (select [#DiscountPrice] = #price for xml path('Product'));
Select #xml

T-SQL retrieving sql attribute from xml using variable

I am trying to retrieve an XML attribute from an XML variable passing in the name of the desired attribute. The first select statement works just fine retrieving the correct attribute values. However, when I try to set within a SQL variable the desired attribute name, all that is displayed is the string /root/attribs/#id instead of the actual value. I have tried numerous permutations of the #path variable, all to no avail.
What am I missing here?
DECLARE #XMLString XML = '<root><attribs flags="1" id="test_id" platform="test_platform" /></root>';
SELECT
flags = x.c.value('(/root/attribs/#flags)[1]', 'nvarchar(50)') ,
id = x.c.value('(/root/attribs/#id)[1]', 'nvarchar(50)') ,
[platform] = x.c.value('(/root/attribs/#platform)[1]', 'nvarchar(50)')
FROM
#XMLString.nodes('/*') x ( c );
DECLARE #Path NVARCHAR(50) = '/root/attribs/#id';
SELECT
result = x.c.value('(sql:variable("#Path"))[1]', 'nvarchar(50)')
FROM
#XMLString.nodes('/*') x ( c );
This will allow you to specify the attribute name.
DECLARE #XMLString xml = '
<root>
<attribs flags="1" id="test_id" platform="test_platform" />
</root>'
DECLARE #Attribute nvarchar(max) = 'flags'
SELECT
t.x.value('(/root/attribs/#*[local-name() = sql:variable("#Attribute")])[1]', 'nvarchar(max)')
FROM #XMLString.nodes('/*') t(x)

Using XQuery in Sql Server to Parse XML Complex types

I have the following XML :
<Feed>
<FeedId>10</FeedId>
<Component>
<Date>2011-10-01</Date>
<Date>2011-10-02</Date>
</Component>
</Feed>
Now if possible I would like to parse the XML into sql so it's serialized into the following relational data:
FeedId Component_Date
10 2011-10-01
10 2011-10-02
However using the following SQL:
DECLARE #XML XML;
DECLARE #XMLNodes XML;
SET #XML = '<Feed><FeedId>10</FeedId><Component><Date>2011-10-01</Date><Date>2011-10-02</Date></Component></Feed>';
SELECT t.a.query('FeedId').value('.', 'INT') AS FeedId
,t.a.query('Component/Date').value('.', 'VARCHAR(80)') AS [Component_Date]
FROM #XML.nodes(' /Feed') AS t(a)
The closest I get is :
FeedId Component_Date
10 2011-10-012011-10-02
So the date values appear in the same row, is it possible to achieve what I want using XQuery?
You need a second call to .nodes() since you have multiple entries inside your XML - try this:
SELECT
t.a.value('(FeedId)[1]', 'INT') AS FeedId,
c.d.value('(.)[1]', 'DATETIME') AS [Component_Date]
FROM
#XML.nodes('/Feed') AS t(a)
CROSS APPLY
t.a.nodes('Component/Date') AS C(D)
Gives me an output of:
FeedId Component_Date
10 2011-10-01 00:00:00.000
10 2011-10-02 00:00:00.000
OK, I can do it using OPENXML method:
eclare #idoc int
DECLARE #XML XML;
DECLARE #XMLNodes XML;
SET #XML = '<Feed><FeedId>10</FeedId><Component><Date>2011-10-01</Date><Date>2011-10-02</Date></Component></Feed>';
exec sp_xml_preparedocument #idoc OUTPUT, #XML
-- SELECT stmt using OPENXML rowset provider
SELECT *
FROM OPENXML (#idoc, '/Feed/Component/Date',1)
WITH (
FeedId Int '../../FeedId',
ComponentDate Date 'text()'
)