for xml explicit dealing with namespace - sql

I'm trying to query explicit xml. For that purposes I have to use namespace. Here is a simplified version:
SELECT 1 as Tag,
NULL as Parent,
i.SSN as [SSN!1]
FROM IRS_Table as i
for xml explicit
But I want xml to look like this:
<irs:SSN>999-99-9999</irs:SSN>
Here is declaration of namespace in the beginning tags:
xmlns:irs="urn:us:gov:treasury:irs:common"
How to revise script so that to see in output namespace?
EDIT
<?xml version="1.0" encoding="utf-8"?>
<n1:Form109495CTransmittalUpstream xmlns:irs="urn:us:gov:treasury:irs:common">
<irs:SSN>999-99-9999</irs:SSN>
</n1:Form109495CTransmittalUpstream>

You can use following query to include namespace into for xml explicitoutput.
SELECT 1 as Tag,
NULL as Parent,
i.SSN as [irs:SSN!1],
'urn:us:gov:treasury:irs:common' as [irs:SSN!1!xmlns:irs] --namespace is here
FROM IRS_Table as i
for xml explicit
Update
Probably easier is to use for xml path construction.
;with xmlnamespaces('urn:us:gov:treasury:irs:common' as irs,
'blahblah' as n1,
default 'blahblah:blah' )
SELECT
null as [n1:Form109495CTransmittalUpstream],
ssn as [n1:Form109495CTransmittalUpstream/irs:SSN]
FROM IRS_Table as i
for xml path(''), elements, root

Related

PostgresSQL xpath with namespaces

I would like to know how to use the xpath funtion in the following example:
The xml is inside a table called SR_DATA, field XMLDATA of type TEXT
The following is the structure of the xml document:
<?xml version="1.0" encoding="UTF-8"?>
<modulo modelCodeScheme="DocType" modelCodeSchemeVersion="01" modelCodeValue="TYPE_20a" modelCodeMeaning="SCREENING" group="groupname" type="format" xmlns="http://www.expr.com/2008/FMSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<AAAAA modelCodeScheme="MAM" modelCodeSchemeVersion="1" modelCodeValue="AN_MAM_6" modelCodeMeaning="Family1" tipodato="booleano">
<![CDATA[false]]>
</AAAAA>
<BBBBB modelCodeScheme="MAM" modelCodeSchemeVersion="1" modelCodeValue="AN_MAM_8" modelCodeMeaning="Family2" tipodato="booleano">
<![CDATA[false]]>
</BBBBB>
</modulo>
Let's say I want to read the text about the element named AAAAA, so my query looks like this:
SELECT (xpath('/modulo/AAAAA/text()', XMLDATA::xml) AS status
FROM SR_DATA;
My query doesn't raise any error but the resultset is empty; I suppose I have to map the NAMESPACES but I need a hint on how to do it.
You need to specify namespaces in the xpath function. The node contains multiple text nodes; you could combine the nodes together using array_to_string function:
SELECT TRIM(BOTH FROM array_to_string(xpath('/x:modulo/x:AAAAA/text()', XMLDATA::xml, ARRAY[
ARRAY['x', 'http://www.expr.com/2008/FMSchema']
]), ''))
FROM SR_DATA
-- false
Demo on db<>fiddle

Extract Value from XML having same tag name in SQL Server

I have XML variable defined below and its value.
I want to fetch the text defined between tag <TextNodeChild> in single query.
Kindly help.
Declare #XMLVariable =
'<?xml version="1.0"?>
<root>
<TextNodeParent>
<TextNodeChild>12345</TextNodeChild>
<TextNodeChild>67890</TextNodeChild>
<TextNodeChild>12389</TextNodeChild>
</TextNodeParent>
</root>'
I need output like this:
12345
67890
12389
You could use the XQuery (i.e. XML query) .nodes() method
SELECT
TextNodeParent = n.value('.[1]', 'NVARCHAR(max)')
FROM
#XMLVariable.nodes('root/TextNodeParent/*') as p(n)
EDIT : If you want to just the select the TextNodeChild node data then little change in xml path as follow
#XMLVariable.nodes('root/TextNodeParent/TextNodeChild') as p(n)
Result
TextNodeParent
12345
67890
12389
#YogeshSharma's solution works - here - because you have nothing but <TextNodeChild> elements under your <TextNodeParent> node.
However, if you had various node, and you wanted to extract only the <TextNodeChild> ones and get their values (and ignore all others), you'd have to use something like this instead:
SELECT
TextNodeParent = XC.value('.', 'INT')
FROM
#XMLVariable.nodes('root/TextNodeParent/TextNodeChild') as XT(XC)

Getting node value in xml column

Please let me know why the following XML query is not fetching any result.
I am trying to get value EffectiveUserName tag.
DECLARE #MyXML XML
SET #MyXML = '<PropertyList xmlns="urn:schemas-microsoft-com:xml-analysis" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<Catalog>name</Catalog>
<Timeout>600</Timeout>
<Format>Native</Format>
<DbpropMsmdFlattened2>false</DbpropMsmdFlattened2>
<Cube>Model</Cube>
<DbpropMsmdOptimizeResponse>1</DbpropMsmdOptimizeResponse>
<DbpropMsmdActivityID>68A6900B-20F8-4A02-AEC3-7C56B2D3C5D5</DbpropMsmdActivityID>
<DbpropMsmdRequestID>A0D1E07F-AE29-4CCA-AEE4-3B79D97CA426</DbpropMsmdRequestID>
<DbpropMsmdCurrentActivityID>68A6900B-20F8-4A02-AEC3-7C56B2D3C5D5</DbpropMsmdCurrentActivityID>
<LocaleIdentifier>1033</LocaleIdentifier>
<EffectiveUserName>userid#domainname.com</EffectiveUserName>
<sspropinitappname>PowerBI</sspropinitappname>
</PropertyList>'
select #MyXML.value('(/PropertyList/EffectiveUserName)[1]','varchar(max)')
Your XML has a default namespace that you must respect and include in your query!
<PropertyList xmlns="urn:schemas-microsoft-com:xml-analysis"
***********************************************
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
Use this code to grab the value you're looking for by defining the default XML namespace for your query:
;WITH XMLNAMESPACES(DEFAULT 'urn:schemas-microsoft-com:xml-analysis')
SELECT
#MyXML.value('(/PropertyList/EffectiveUserName)[1]', 'varchar(50)')
You can ignore the namespace by using *: before the tag names:
select #MyXML.value('(/*:PropertyList/*:EffectiveUserName)[1]','varchar(max)')

Having trouble parsing some xml

I am trying to parse some XML that has been put into a column. To simplify, I have put the XML directly into a variable and tried to parse it here.
Declare #XMLToParse XML
SELECT #XMLToParse = '<?xml version="1.0" encoding="UTF-8"?>
<atn:Transaction xmlns:atn="http://www.agcs.com/Transaction/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.agcs.com/Transaction/cosmos.xsd">
<name>AIRW0043</name>
<address>654577</address>
</atn:Transaction>'
;WITH XMLNAMESPACES(DEFAULT 'http://www.agcs.com/Transaction/cosmos.xsd',
'http://www.agcs.com/Transaction/' as atn)
Select #XMLToParse.value('data(/atn:Transaction/name)[1]','VARCHAR(100)') namecode
, #XMLToParse.value('data(/atn:Transaction/address[1]','VARCHAR(100)') addresscode
I am getting null for both values (namecode and addresscode). I should get the name value in namecode and the address value in addresscode.
The actual problem was that you're setting default namespace in WITH XMLNAMESPACES statement. That causes all elements without explicit prefix in your XPath/XQuery (f.e /name and /address) to be considered in the default namespace -while in the actual XML they are in no namespace-.
So in short, simply remove default namespace from your WITH XMLNAMESPACES statement :
Declare #XMLToParse XML
SELECT #XMLToParse = '<?xml version="1.0" encoding="UTF-8"?>
<atn:Transaction xmlns:atn="http://www.agcs.com/Transaction/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.agcs.com/Transaction/cosmos.xsd">
<name>AIRW0043</name>
<address>654577</address>
</atn:Transaction>'
;WITH XMLNAMESPACES('http://www.agcs.com/Transaction/' as atn)
Select #XMLToParse.value('data(/atn:Transaction/name)[1]','VARCHAR(100)') namecode
, #XMLToParse.value('data(/atn:Transaction/address)[1]','VARCHAR(100)') addresscode
you need to use 'text()' to get the element value
;WITH XMLNAMESPACES('http://www.agcs.com/Transaction/' as atn)
Select #XMLToParse.value('(/atn:Transaction/name/text())[1]','VARCHAR(100)') namecode
, #XMLToParse.value('(/atn:Transaction/address/text())[1]','VARCHAR(100)') addresscode

How to get specific XML namespace in XQuery in SQL Server

I have a XML that I need one specific namespace according to node like temprature with hls i need namespace of that "http://www.schema.hls.com/extension" I have tried with these
DECLARE #EventXML AS XML
SET #EventXML='<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns:test xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ns="urn:global:test:xsd:1"
xmlns:hls="http://schema.hls.com/extension" creationDate="2007-01-25T00:00:00Z"
schemaVersion="1.0">
<TestBody>
<TestList>
<TestEvent>
<hls:temperature>20</hls:temperature>
</TestEvent>
</TestList>
</TestBody>
</ns:test>'
SELECT
OE.value('#ns','varchar(50)') + '#' + OE.value('fn:local-name(.)[1]','varchar(50)'),
OE.value('#id','varchar(50)'),
CONVERT(VARCHAR(4000),CASE WHEN OE.exist('./*') =1 THEN OE.query('./*') ELSE
OE.value('./text()[1]','varchar(100)') END)
FROM #EventXML.nodes('//TestEvent/*') TestEvent(OE)
WHERE OE.value('fn:local-name(.)[1]','varchar(50)') IN --(#tag)
(SELECT Split.a.value('.', 'VARCHAR(100)') AS extag
FROM (SELECT CONVERT(XML,'<M>' + REPLACE(ISNULL('temperature','0'), ',', '</M><M>') + '</M>') AS String
) AS A CROSS APPLY String.nodes ('/M') AS Split(a))
I am using these in SQL query window but getting only third column value 20 not get namespace by #ns
Please suggest how to get the namespace
OE.value('#ns','varchar(50)')
by these.
thanks in advanced.
Your code and XML somehow just don't quite match up - and the query is really quite confusing....
If you want to fetch the data, you must respect the XML namespaces in play. You need to declare them with a WITH XMLNAMESPACES() construct, and you need to use them in your XPath.
But also: the node you're selecting (<hls:temperature>) doesn't really have any id and ns attributes..... so of course you're not getting any values!
I tried to use a trimmed down version and I added the two attributes - just to show how to use the XML namespaces stuff in your code.
Here it comes:
DECLARE #EventXML AS XML
SET #EventXML =
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns:test xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ns="urn:global:test:xsd:1"
xmlns:hls="http://schema.hls.com/extension"
creationDate="2007-01-25T00:00:00Z" schemaVersion="1.0">
<TestBody>
<TestList>
<TestEvent>
<hls:temperature ns="test" id="42">20</hls:temperature>
</TestEvent>
</TestList>
</TestBody>
</ns:test>'
-- define your XML namespaces that are in play.
-- You *MUST* match the namespace definition, but the *prefixes* that you define
-- can be something else entirely than in the XML document!
-- Of course, inside your XPath, you *MUST* use the defined prefixes!
;WITH XMLNAMESPACES('urn:global:test:xsd:1' AS x1,
'http://schema.hls.com/extension' AS x2)
SELECT
OE.value('#ns', 'varchar(50)'),
OE.value('#id', 'varchar(50)')
FROM
#EventXML.nodes('/x1:test/TestBody/TestList/TestEvent/x2:*') TestEvent(OE)
This code - using the XML namespaces defined and used in your XML - produces this output:
(No column name) (No column name)
test 42
So this shows how you can access the attributes - if they are present! - on your XML nodes, even with the presence of XML namespaces.