How can I select tags from an SQL XML Query? - sql

How can I retrieve the fields within an XML field in MS SQL?
Every query I try does not work as intended whenever I use this XML code:
I want to select the AccNumber value.
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Header>
<AuthSoapHd xmlns="https://temp.uri.com/Mngmt/">
<System>System1</System>
</AuthSoapHd>
</soap:Header>
<soap:Body>
<PrintList xmlns="https://temp.uri.com/Mngmt/">
<Account>
<AccNumber xmlns="https://temp.uri.com/Project/Object/Data">990368644</AccNumber>
</Account>
</PrintList>
</soap:Body>
</soap:Envelope>
I tried multiple varations of the following with no sucess
Select [RequestXML].query('/Envelope/Body/PrintList/Account/AccNumber')
FROM [dbo].[Table1]

You're ignoring the XML namespace that is in play - you need to pay attention to that!
WITH XMLNAMESPACES('http://schemas.xmlsoap.org/soap/envelope/' AS soap,
'https://temp.uri.com/Project/Object/Data' AS data,
'https://temp.uri.com/Mngmt/' AS mgmt)
SELECT
RequestXML.value('(/soap:Envelope/soap:Body/mgmt:PrintList/mgmt:Account/data:AccNumber)[1]',
'BIGINT') AS 'AccNumber'
FROM
[dbo].[Table1]
That hopefully works!

Related

Import field in XML using SQL not working

i've been trying to import the field GivenName in my example XML but for some reason it's not working, i've been using the following SQL query, i think i'm using the correct field and the correct nodes but i'm not 100% sure about the XMLNameSpaces
Thank you very much in advance for your help
This is the example SQL Query i'm using:
DECLARE #xml XML = (SELECT [Xml] FROM ExampleTable)
;WITH XMLNAMESPACES (DEFAULT 'http://www.opentravel.org/OTA/2003/05','http://www.w3.org/2003/05/soap-envelope' )
select FirstName = ProfileInfo.value('Profiles[1]/ProfileInfo[1]/Profile[1]/Customer[1]/PersonName[1]/#GivenName', 'nvarchar(255)')
FROM #xml.nodes('Envelope/Body/OTA_Example/Info/Infos/ResUser') as T1(Profiles)
outer apply T1.Profiles.nodes('ResUser2') as T2(ProfileInfo)
This is the example XML i'm using for the import:
<Envelope xmlns="http://www.w3.org/2003/05/soap-envelope">
<soap2:Header xmlns:htng="http://htng.org/1.3/Header/" xmlns:wsa="http://www.w3.org/2005/08/addressing"
xmlns:wss="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:htnga="http://htng.org/PWSWG/2007/02/AsyncHeaders"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:soap2="http://www.w3.org/2003/05/soap-envelope">
<wsa:Action>Example</wsa:Action>
<wsa:ReplyTo>
<wsa:Address>Example2</wsa:Address>
</wsa:ReplyTo>
<htnga:ReplyTo>
<wsa:Address>Example3</wsa:Address>
</htnga:ReplyTo>
<wsa:MessageID>123</wsa:MessageID>
</soap2:Header>
<Body>
<OTA_Example xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.opentravel.org/OTA/2003/05" Version="5.000" >
<Info>
<Infos CreateDateTime="2021-09-20T06:52:40" CreatorID="User">
<UniqueID Type="1" ID="12341251" />
<ResUser>
<ResUser2 ResGuestRPH="1" PrimaryIndicator="true">
<Profiles>
<ProfileInfo>
<Profile ProfileType="1">
<Customer>
<PersonName>
<NamePrefix>Mr.</NamePrefix>
<GivenName>FirstnameTest</GivenName>
<Surname>LastnameTest</Surname>
</PersonName>
</Customer>
</Profile>
</ProfileInfo>
</Profiles>
</ResUser2>
</ResUser>
</Infos>
</Info>
</OTA_Example>
</Body>
</Envelope>
GivenName is not an attribute, so you shouldn't use # for it.
It's unclear why you needed .nodes, it is only needed if there were multiple nodes that needed breaking out into separate rows
You can also select straight out of ExampleTable, you do not need to store it in a variable.
;WITH XMLNAMESPACES (
'http://www.w3.org/2003/05/soap-envelope' AS soap,
DEFAULT 'http://www.opentravel.org/OTA/2003/05')
select FirstName = [XML].value('(soap:Envelope/soap:Body/OTA_Example/Info/Infos/ResUser/ResUser2/Profiles/ProfileInfo/Profile/Customer/PersonName/GivenName/text())[1]', 'nvarchar(255)')
FROM ExampleTable
db<>fiddle

T-sql select xml value

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<Teste xmlns="http://google.com">
<Username></Username>
<Password></Password>
<Firma>Blabla</Firma>
</Teste>
</soap:Header>
<soap:Body>
-- Omitted
</soap:Body>
</soap:Envelope>
Having this xml in a column, how to retrieve the Firma value ? What's giving me more trouble is the "soap" namespaces that seem to be ruining my query's
This is what I was experimenting with, but not working as expected since the path is wrong
select ref.col.value('.','varchar(255)')
from my_View tbl
cross apply tbl.XMLColumn.nodes('Envelope/Header/Teste/Firma') as ref(col)
You must use namespaces in your Xquery
create table so_Test (XMLColumn xml)
go
insert so_Test
select '<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<Teste xmlns="http://google.com">
<Username></Username>
<Password></Password>
<Firma>Blabla</Firma>
</Teste>
</soap:Header>
<soap:Body>
</soap:Body>
</soap:Envelope>'
select XMLColumn.value('
declare namespace soap="http://schemas.xmlsoap.org/soap/envelope/";
declare namespace google="http://google.com";
/soap:Envelope[1]/soap:Header[1]/google:Teste[1]/google:Firma[1]', 'varchar(255)') as Firma from so_test
Result:
Firma
Blabla

Save data into table from soap xml

I am trying to save data values into a table so that I can use them but can't get my head around it. I am currently running SQL Server 2012. How do I read soap XML which is saved in #x variable?
declare #x xml
set #x = '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<ListResponse xmlns="http://api.com">
<ListResult>
<API>
<ID>1565</ID>
<Email>jd#dj.com</Email>
<Type>Unknown</Type>
<Notes />
</API>
</ListResult>
</ListResponse>
</soap:Body>
</soap:Envelope>'
This is what I come up but it is only returning data in a single column with no way of knowing which data belongs to which column
select convert(varchar, n.c.value('.', 'varchar(max)'))
from #X.nodes('//text()[1]') n(c)
1565
jd#dj.com
Unknown
Data is coming in column format where as i wants in row with each API returns. currently only 1 API return what if more then 1 ?

SqlServer XQuery always concat two fields

I want to get somedata from one column only from an xml field:
<CDirData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://Fnet.ESB.Schemas.CentroDirectivo.CDirData">
<ProcedureData xmlns="">
<ProcedureId>7001</ProcedureId>
<CentroDirectivo>Subsecretaria</CentroDirectivo>
</ProcedureData>
<SolicitudData xmlns="">
...
with my query
SELECT top 1
[Message].query('//*[local-name()="ProcedureId"]').value('.','nvarchar(max)') as R
from
ManagementCenterQueueHistorical
but allways returns the fields concat
I would need just only the first one
Thanks in advance!
Put your XPath expressin in parenthessis and add [1] to get only first element from the group
DECLARE #x XML = '<CDirData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://Fnet.ESB.Schemas.CentroDirectivo.CDirData">
<ProcedureData xmlns="">
<ProcedureId>7001</ProcedureId>
<CentroDirectivo>Subsecretaria1</CentroDirectivo>
</ProcedureData>
<ProcedureData xmlns="">
<ProcedureId>7002</ProcedureId>
<CentroDirectivo>Subsecretaria2</CentroDirectivo>
</ProcedureData>
<ProcedureData xmlns="">
<ProcedureId>7003</ProcedureId>
<CentroDirectivo>Subsecretaria3</CentroDirectivo>
</ProcedureData>
<ProcedureData xmlns="">
<ProcedureId>7004</ProcedureId>
<CentroDirectivo>Subsecretaria4</CentroDirectivo>
</ProcedureData>
</CDirData>'
SELECT
#x.query('(//*[local-name()="ProcedureId"])[1]').value('.','nvarchar(max)') as R

How can I select tags from an SQL XML Query?

How can I retrieve the fields within an XML field in MS SQL?
Every query I try does not work as intended whenever I use this XML code:
<soap:Envelope xmlns:xsi="[URI]" xmlns:xsd="[URI]" xmlns:soap="[URI]">
<soap:Body>
<RunPackage xmlns="[URI]">
<xmlDoc>
<Request>
<SubscriberCode>76547654</SubscriberCode>
<CompanyCode></CompanyCode>
</Request>
</xmlDoc>
</RunPackage>
</soap:Body>
</soap:Envelope>
I don't know how to reference the first two tags. I've tried
SELECT TransactionID, T2.Loc.query('data(Request/SubscriberCode)') as 'SubscriberCode'
FROM TempWorksRequest
CROSS APPLY RequestXML.nodes('soap:Envelope/soap:Body/RunPackage/xmlDoc') as T2(Loc)
With no luck.
You need to declare the XML namespaces ("soap" in this case, plus another one for the node and anything below) in your XQuery operations:
SELECT
TransactionID,
T2.Loc.query('declare namespace ns="[URI1]";data(ns:Request/ns:SubscriberCode)')
as 'SubscriberCode'
FROM
TempWorksRequest
CROSS APPLY
RequestXML.nodes('declare namespace soap="[URI]";
declare namespace ns="[URI1]";
soap:Envelope/soap:Body/ns:RunPackage/ns:xmlDoc') as T2(Loc)
[URI1] needs to be the URI that's defined on the <RunPackage> tag.
Marc