How to get value of a node with namespace prefix [duplicate] - sql

This question already has answers here:
sql server parse xml with namespace
(2 answers)
Closed 11 months ago.
So, I have got the following query that I tried to get the value between the nodes:
<oas:Base64Assertion>235fkl53</oas:Base64Assertion>
I want to extract the value 235fkl53. I tried with the following query:
declare #x xml = '
<soapenv:Header>
<oas:Security>
<oas:Base64Assertion>
<oas:Security xmlns:oas="http://example.com">
<oas:Base64Assertion>235fkl53</oas:Base64Assertion>
</oas:Security>
</oas:Base64Assertion>
</oas:Security>
</soapenv:Header>
';
select cast(#x.value('(//oas:Base64Assertion)[1]', 'nvarchar(max)') as xml).query('//value/text()') as cdata;
But I get the following error:
Msg 2229, Level 16, State 1, Line 13 XQuery [value()]: The name "oas"
does not denote a namespace.
Any tips on how to achieve this?

You did not add the namespaces in the XML you posted so I have added them in the following example based on where I think they should be.
You need to add WITH NAMESPACE before using namespace prefixes in XQueries:
declare #x xml = '<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" xmlns:oas="http://example.com">
<soapenv:Header>
<oas:Security>
<oas:Base64Assertion>
<oas:Security>
<oas:Base64Assertion>235fkl53</oas:Base64Assertion>
</oas:Security>
</oas:Base64Assertion>
</oas:Security>
</soapenv:Header>
</soapenv:Envelope>
';
WITH XMLNAMESPACES ('http://example.com' AS oas)
SELECT #x.value('(//oas:Base64Assertion)[1]', 'nvarchar(max)');
SELECT #x.value('declare namespace oas="http://example.com"; (//oas:Base64Assertion)[1]', 'nvarchar(max)');
DB<>Fiddle

Related

Error "The name "soap" does not denote a namespace" if i try to parse XML in T-sql

When i try to parse XML in T-sql I get error "The name "soap" does not denote a namespace"
This is my XML and query. Answer, please, how can I parse such XML. Thanks.
DECLARE #xml xml
SET #xml =
'<soap:Envelope xmlns:soap=http://schemas.xmlsoap.org/soap/envelope/>
<soap:Body>
<GetWebLinkResponse xmlns=http://test.org/ xmlns:ns2=http://schemas.datacontract.org/2004/07/.Configuration xmlns:ns3=http://schemas.datacontract.org/2004/07/.Configuration.Results xmlns:ns4=http://schemas.microsoft.com/2003/10/Serialization/>
<GetWebLinkResult>
<ns3:Error>
<ns2:Id>0</ns2:Id>
<ns2:Text>Success.</ns2:Text>
</ns3:Error>
<ns3:Url>
https://example.com&content=true
</ns3:Url>
</GetWebLinkResult>
</GetWebLinkResponse>
</soap:Body>
</soap:Envelope>'
SELECT
-- n.value('(./Code/text())[1]','int') as CODE
--,
n.value('ns3:Url','varchar(1000)')as NAME
FROM #xml.nodes('/soap:Envelope/soap:Body/GetWebLinkResponse/GetWebLinkResult') as a(n)
First of all - your XML is invalid - your namespace definitions must be in double quotes:
DECLARE #xml xml
SET #xml =
'<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<GetWebLinkResponse xmlns="http://test.org/" xmlns:ns2="http://schemas.datacontract.org/2004/07/.Configuration" xmlns:ns3="http://schemas.datacontract.org/2004/07/.Configuration.Results" xmlns:ns4="http://schemas.microsoft.com/2003/10/Serialization/">
<GetWebLinkResult>
<ns3:Error>
<ns2:Id>0</ns2:Id>
<ns2:Text>Success.</ns2:Text>
</ns3:Error>
<ns3:Url>
https://example.com&content=true
</ns3:Url>
</GetWebLinkResult>
</GetWebLinkResponse>
</soap:Body>
</soap:Envelope>';
Once you've corrected that, you'll need to define all relevant XML namespaces for your T-SQL query. Relevant XML namespaces are all explicitly used namespaces (like soap: and ns3:), as well as default namespaces like the xmlns="http://test.org/" on your <GetWebLinkResponse> node.
When you declare them all - the T-SQL query should work:
WITH XMLNAMESPACES('http://schemas.xmlsoap.org/soap/envelope/' AS soap,
'http://schemas.datacontract.org/2004/07/.Configuration.Results' as ns3,
DEFAULT 'http://test.org/')
SELECT
n.value('(ns3:Url)[1]', 'varchar(1000)') AS NAME
FROM
#xml.nodes('/soap:Envelope/soap:Body/GetWebLinkResponse/GetWebLinkResult') as a(n)

Extract xml value from table SQL Server

I am trying to extract value from xml in table.PFB sample xml.
<?xml version="1.0" encoding="utf-16"?>
<ArrayOfKeyValue xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<KeyValue>
<Key>[#Id#]</Key>
<Value>354005</Value>
</ArrayOfKeyValue>
I am trying below script and it is not working.
SELECT
CAST(CAST(([KeyWordValues]) AS ntext) AS XML).value('(/ArrayOfKeyValue/KeyValue[1])', 'nvarchar(max)')
FROM
Table
I'm getting this error :
Msg 2389, Level 16, State 1, Line 1
XQuery [value()]: 'value()' requires a singleton (or empty sequence), found operand of type 'xdt:untypedAtomic *'
Please note XML is saved as varchar in the database.
Please help. Thanks in advance
Thanks alot for help. I got it working.
SELECT cast(cast(([KeyWordValues]) as ntext) as
xml).value('(/ArrayOfKeyValue/KeyValue/Value)[1]', 'nvarchar(max)')
FROM Table

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)')

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.

adding encoding information to the result of FOR XML [duplicate]

This question already has answers here:
SQL Server FOR XML Enclosing Element?
(2 answers)
Closed 7 years ago.
I have a Script, which returns a XML using FOR XML in SQL 2008. Is there any way to add the version and encoding information in the beginning of the output. Eventually, i am planning to save the output in a file.
For example, right now my output looks like this
<Agents>
<Agent id="1">
<Name>Mike</Name>
<Location>Sanfrancisco</Location>
</Agent>
<Agent id="2">
<Name>John</Name>
<Location>NY</Location>
</Agent>
</Agents>
I would like to append the line <?xml version="1.0" encoding="UTF-8"?> in the beginning of the Xml output
So i want the output something like
<?xml version="1.0" encoding="UTF-8"?>
<Agents>
<Agent id="1">
<Name>Mike</Name>
<Location>Sanfrancisco</Location>
</Agent>
<Agent id="2">
<Name>John</Name>
<Location>NY</Location>
</Agent>
As #gbn points out in another answer and on another question, "the XML data is stored internally as ucs-2", and SQL Server doesn't include it when producing the data. However, you can convert the XML to a string and append the XML declaration at the beginning manually. However, simply using UTF-8 in the declaration would be inaccurate. The Unicode string which SQL produces is in UCS-2. For example, this will fail:
SELECT CONVERT(xml,N'<?xml version="1.0" encoding="UTF-8"?>' + CONVERT(NVARCHAR(MAX),CONVERT(XML,N'<x>' + NCHAR(10176) + N'</x>')));
with error:
Msg 9402, Level 16, State 1, Line 1 XML parsing: line 1, character 38,
unable to switch the encoding
This, on the other hand, will work as expected:
SELECT CONVERT(xml,N'<?xml version="1.0" encoding="UCS-2"?>' + CONVERT(NVARCHAR(MAX),CONVERT(XML,N'<x>' + NCHAR(10176) + N'</x>')));
Here is code which will produce the full, declaration-laden XML string you seek for your example data:
DECLARE #Agents TABLE
(
AgentID int,
AgentName nvarchar(50),
AgentLocation nvarchar(100)
);
INSERT INTO #Agents (AgentID, AgentName, AgentLocation) VALUES (1, N'Mike', N'Sanfrancisco');
INSERT INTO #Agents (AgentID, AgentName, AgentLocation) VALUES (2, N'John', N'NY');
WITH BaseData AS
(
SELECT
(
SELECT
AgentID AS '#id',
AgentName AS 'Name',
AgentLocation AS 'Location'
FROM #Agents
FOR XML PATH('Agent'), ROOT('Agents'), TYPE
) AS AgentXML
), FullStringTable AS
(
SELECT
*,
'<?xml version="1.0" encoding="UCS-2"?>' +
CONVERT(nvarchar(max),AgentXML) AS FullString
FROM BaseData
)
SELECT
AgentXML AS OriginalXML,
FullString,
CONVERT(xml,FullString) AS FullStringConvertedToXML
FROM FullStringTable;
SQL Server internally always uses utf-16 ucs-2 so you could just append it like we did. That is, SQL Server would never generate anything with "utf-8".
Edit: after some digging:
http://www.devnewsgroups.net/group/microsoft.public.sqlserver.xml/topic60022.aspx
http://forums.asp.net/t/1455808.aspx
If you will not be attempting to manipulate the results as TSQL XML then the simplest thing to do will be create a varchar with the string you wish to append then add the XML to it using a CAST statemnt to convert the XML to varchar.
declare #testXML as XML
declare #testPrefix as varchar(255)
set #testPrefix = '<?xml version="1.0" encoding="UTF-8"?>'
set #testXML = '<Agents> <Agent id="1"> <Name>Mike</Name> <Location>Sanfrancisco</Location> </Agent> <Agent id="2"> <Name>John</Name> <Location>NY</Location> </Agent></Agents>'
select #testPrefix
Select #testXML
select #testPrefix + CAST(#testXML as varchar(max))