SQL Extract Value from XML - sql

I have the following XML and I want to extract the FieldValue using SQL. How can I do this?
<Field Group="Annuitant">
<FieldName>Contract Number</FieldName>
<FieldValue>TR13116544</FieldValue>
</Field>
Thanks

DECLARE #xml XML=
'<Field Group="Annuitant">
<FieldName>Contract Number</FieldName>
<FieldValue>TR13116544</FieldValue>
</Field>';
--the lazy approach
SELECT #xml.value('(//FieldValue)[1]','varchar(50)')
--Better
SELECT #xml.value('(/Field/FieldValue)[1]','varchar(50)')
--This is, what you should do: Be as specific as possible...
SELECT #xml.value('(/Field/FieldValue/text())[1]','varchar(50)')
If there are - what I assume - are several <Field> elements and you need to pick the rigth one, you can do something like this:
DECLARE #name VARCHAR(100)='Contract Number';
SELECT #xml.value('(/Field[(FieldName/text())[1]=sql:variable("#name")]/FieldValue/text())[1]','varchar(50)')
Hint: Your question is not very clear, that needs a lot of guessing on my side. For your next question I ask you to be more specific.

Sample code:
DECLARE #MyXML XML
SET #MyXML ='<SampleXML>
<Fruits>
<Fruits1>Apple</Fruits1>
<Fruits2>Pineapple</Fruits2>
</Fruits>
</SampleXML>'
SELECT
a.b.value('Fruits[1]/Fruits1[1]','varchar(10)') AS Fruits1,
a.b.value('Fruits[1]/Fruits2[1]','varchar(10)') AS Fruits2
FROM #MyXML.nodes('SampleXML') a(b)

In oracle you can do the following:
WITH TABL (FIELD) AS (
select xmltype('<Field Group="Annuitant">
<FieldName>Contract Number</FieldName>
<FieldValue>TR13116544</FieldValue>
</Field>') from dual
)
SELECT
EXTRACTVALUE(FIELD,'/Field/FieldName') AS FIELDNAME,
EXTRACTVALUE(field,'/Field/FieldValue') AS FieldValue
FROM TABL ;

Related

Trying to access an XML node value from a table column using query in SQL Server and it always returns an empty string

Have a table called UserRequest and one column of the is XML type (column name is RequestXML). The values in RequestXML will be something like this:
<MyRequest xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://schemas.datacontract.org/2004/07/">
<transfer>
<Field>
<fieldId>12323</fieldId>
<FieldDetails>
<RequestInfoField>
<requestDecs>Test</requestDecs>
<reqDate>01/01/2021</reqDate>
</RequestInfoField>
<identifierKey>45638</identifierKey>
</FieldDetails>
</Field>
</transfer>
</MyRequest>
Using the following SQL query to retrieve the XML node value of identifierKey, but the query is always returning an empty string :
select
T.RequestXML.query('MyRequest/transfer/Field/FieldDetails/identifierKey') As identifierKey, *
from UserRequest T
You haven't declared your (default) namespace in your SQL:
WITH XMLNAMESPACES(DEFAULT 'http://schemas.datacontract.org/2004/07/')
SELECT UR.RequestXML.query('MyRequest/transfer/Field/FieldDetails/identifierKey') As identifierKey,
*
FROM dbo.UserRequest UR;
If you, however, explicitly want the value of identifierKey use value, not query.
WITH XMLNAMESPACES(DEFAULT 'http://schemas.datacontract.org/2004/07/')
SELECT UR.RequestXML.value('(MyRequest/transfer/Field/FieldDetails/identifierKey)[1]','int') AS identifierKey
*
FROM dbo.UserRequest UR;
db<>fiddle
Like this:
declare #doc xml = '<MyRequest xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://schemas.datacontract.org/2004/07/">
<transfer>
<Field>
<fieldId>12323</fieldId>
<FieldDetails>
<RequestInfoField>
<requestDecs>Test</requestDecs>
<reqDate>01/01/2021</reqDate>
</RequestInfoField>
<identifierKey>45638</identifierKey>
</FieldDetails>
</Field>
</transfer>
</MyRequest>';
WITH XMLNAMESPACES(DEFAULT 'http://schemas.datacontract.org/2004/07/')
SELECT T.RequestXML.value('(/MyRequest/transfer/Field/FieldDetails/identifierKey)[1]','int') As identifierKey, *
FROM (values(#doc)) T(RequestXML);

Retrieve all XML elements with the same prefix in SQL Server

I have an XML file in a format similar to:
<XML>
<Field1>100</Field1>
<Field2>200</Field2>
<Field3>300</Field3>
<Test>400</Test>
</XML>
I need to write a query that will get all of the element values that start with Field. So given the XML above the result should be
FieldVal
--------
100
200
300
I've tried the following but it does not work:
Select
xc.value('text()', 'int')
From
#XMLData.nodes('/XML/[starts-with(name(), ''Field'')]') As xt(xc)
NOTE: I am well aware that this task could be easily done if I reformatted my XML but unfortunately I have no control over the format of the XML.
One way is
declare #XMLData xml ='<XML>
<Field1>100</Field1>
<Field2>200</Field2>
<Field3>300</Field3>
<Test>400</Test>
</XML>'
Select
xc.value('.', 'int')
From #XMLData.nodes('/XML/*') As xt(xc)
WHERE xc.value('local-name(.)', 'varchar(50)') LIKE 'Field%'
Prefix name with special character and check contains instead.
declare #x xml ='<XML>
<Field1>100</Field1>
<Field2>200</Field2>
<Field3>300</Field3>
<Test>400</Test>
</XML>';
select t.n.value('.','varchar(100)')
from #x.nodes ('XML/*[contains(concat("$",local-name()),"$Field")]') t(n);
I think it's this what you are looking for:
DECLARE #xml XML=
'<XML>
<Field1>100</Field1>
<Field2>200</Field2>
<Field3>300</Field3>
<Test>400</Test>
</XML>';
SELECT Fld.value('.','int') AS FieldOnly
FROM #xml.nodes('/XML/*[substring(local-name(.),1,5)="Field"]') AS A(Fld)
Just because of the discussion in comments:
DECLARE #fldName VARCHAR(100)='Field';
SELECT Fld.value('.','int') AS FieldOnly
FROM #xml.nodes('/XML/*[substring(local-name(.),1,string-length(sql:variable("#fldName")))=sql:variable("#fldName")]') AS A(Fld)
Change the first line to "Test" (case sensitive!), and you'd get just the one row with 400...

extract datav values for XML column with XML namespaces in SQL Server

Can anybody please help me with the below xml. I need extract all the xml values like below.
AwarYear Comments FieldCode FieldNumber Key Value
AY2013-14 AAI: Adjusted Available Income AAI 306 Blank None Calculated
Here is the sample XML.
<SchemaType xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/process">
<AwardYear>AY2013_14</AwardYear>
<Fields>
<FieldSchema>
<Comments>AAI: Adjusted Available Income</Comments>
<DbLocation>IsirData</DbLocation>
<FieldCode>AAI</FieldCode>
<FieldNumber>306</FieldNumber>
<ReportDisplay>Data</ReportDisplay>
<ValidContent>
<ValidValueContent xmlns:d5p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<d5p1:KeyValueOfstringstring>
<d5p1:Key>Blank</d5p1:Key>
<d5p1:Value>None calculated</d5p1:Value>
</d5p1:KeyValueOfstringstring>
</ValidValueContent>
</ValidContent>
</FieldSchema>
</Fields>
</SchemaType>
Please do the need full. Thanks in advance.
Assuming you have your XML in a table inside an XML column like this:
DECLARE #XmlTable TABLE (ID INT NOT NULL, XMLDATA XML)
INSERT INTO #XmlTable VALUES(1, '<SchemaType xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/process">
<AwardYear>AY2013_14</AwardYear>
<Fields>
<FieldSchema>
<Comments>AAI: Adjusted Available Income</Comments>
<DbLocation>IsirData</DbLocation>
<FieldCode>AAI</FieldCode>
<FieldNumber>306</FieldNumber>
<ReportDisplay>Data</ReportDisplay>
<ValidContent>
<ValidValueContent xmlns:d5p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<d5p1:KeyValueOfstringstring>
<d5p1:Key>Blank</d5p1:Key>
<d5p1:Value>None calculated</d5p1:Value>
</d5p1:KeyValueOfstringstring>
</ValidValueContent>
</ValidContent>
</FieldSchema>
</Fields>
</SchemaType>')
then you can use this T-SQL statement to fetch the values:
;WITH XMLNAMESPACES(DEFAULT 'http://schemas.datacontract.org/process',
'http://schemas.microsoft.com/2003/10/Serialization/Arrays' AS ns1)
SELECT
AwardYear = XmlData.value('(SchemaType/AwardYear)[1]', 'varchar(25)'),
Comments = XmlData.value('(SchemaType/Fields/FieldSchema/Comments)[1]', 'varchar(50)'),
FieldCode = XmlData.value('(SchemaType/Fields/FieldSchema/FieldCode)[1]', 'varchar(10)'),
FieldNumber = XmlData.value('(SchemaType/Fields/FieldSchema/FieldNumber)[1]', 'int'),
[Key] = XmlData.value('(SchemaType/Fields/FieldSchema/ValidContent/ValidValueContent/ns1:KeyValueOfstringstring/ns1:Key)[1]', 'varchar(10)'),
[Value] = XmlData.value('(SchemaType/Fields/FieldSchema/ValidContent/ValidValueContent/ns1:KeyValueOfstringstring/ns1:Value)[1]', 'varchar(10)')
FROM
#XmlTable
I defined the top-level XML namespace as the "default" namespace (that doesn't need to be referenced all over the place), and the second namespace deep inside your structure is defined explicitly with a separate XML namespace prefix.

Getting the value of dc:creator using SQL XML

I am unsure how to get the value of dc:creator from an RSS-feed using SQL.
This is my xml/rss-feed:
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
<channel>
<title>Foobar RSS</title>
<link>http://www.foobar.com/</link>
<description>RSS feed</description>
<language>en</language>
<ttl>15</ttl>
<item>
<title>This is my title</title>
<link>http://www.foobar.com/link/blabla</link>
<description>Bla..bla..bla..</description>
<dc:creator>John Doe</dc:creator>
<guid isPermaLink="false">00082EA751F1D905DE00E7CFA2417DA9</guid>
<pubDate>Wed, 26 Oct 2011 00:00:00 +0200</pubDate>
</item>
</channel>
</rss>
In my SQL I use something like this to get the values - e.g for pubDate I use something like this:
DECLARE #xml XML
SET #xml = cast('my rss feed here' AS xml)
SELECT
convert(datetime,substring(T.nref.value('pubDate[1]','nvarchar(100)'),6,20)) as pubdate,
FROM #xml.nodes('//item') AS T(nref)
This works fine, but when I am trying to get dc:creator value 'John Doe', the following just gives me an error:
SELECT
T.nref.value('dc:creator','nvarchar(100)') as creator
FROM #xml.nodes('//item') AS T(nref)
error:
XQuery [value()]: The name "dc" does not denote a namespace.
I need to be able to select multiple columns from the rss-feed. Can anybody provide a solution or direction to get the value of dc:creator?
I have another question - how would you construct the code if you are doing it in a sub select?
E.g.
INSERT INTO RSSResults (ID, pubDate)
SELECT #ID, tbl.pubDate FROM (
;WITH XMLNAMESPACES('http://purl.org/dc/elements/1.1/' AS dc)
SELECT
RSS.Item.value('(dc:creator)[1]', 'nvarchar(100)') as pubDate
FROM
#xml.nodes('/rss/channel/item') as RSS(Item)) AS tbl
The code breaks at ";WITH XMLNAMESPACES". Is it possible to include the namespace directly in the statement somehow?
Try something like this:
DECLARE #xml XML
SET #xml = cast('my rss feed here' AS xml)
;WITH XMLNAMESPACES('http://purl.org/dc/elements/1.1/' AS dc)
SELECT
#xml.value('(rss/channel/item/dc:creator)[1]', 'nvarchar(100)')
If you need to catch multiple items - try this:
DECLARE #xml XML
SET #xml = cast('my rss feed here' AS xml)
;WITH XMLNAMESPACES('http://purl.org/dc/elements/1.1/' AS dc)
SELECT
RSS.Item.value('(dc:creator)[1]', 'nvarchar(100)')
FROM
#xml.nodes('/rss/channel/item') as RSS(Item)

Retrieving XML element name using t-SQL

If I have:
<quotes>
<quote>
<name>john</name>
<content>something or other</content>
</quote>
<quote>
<name>mary</name>
<content>random stuff</content>
</quote>
</quotes>
How do I get a list of the element names 'name' and 'content' using T-SQL?
The best I've got so far is:
declare #xml xml
set #xml = ...
select r.value('quotes/name()[1]', 'nvarchar(20)' as ElementName
from #xml.nodes('/quotes') as records(r)
But, of course, I can't get this to work.
Actually, sorry, the best I've got is:
select distinct r.value('fn:local-name(.)', 'nvarchar(50)') as t
FROM
#xml.nodes('//quotes/*/*') AS records(r)
Guess I answered my own question...
DECLARE #xml as xml
SET #xml = '<Address><Home>LINE1</Home></Address>'
SELECT Nodes.Name.query('local-name(.)') FROM #xml.nodes('//*') As Nodes(Name)
This will give the list of all elements