Reputation: 13
I am trying to parse some xml from a SOAP API. I am quite new to XML, but i can get it to work when i only have the body of the statement. I have tried applying some simple namespaces, but I am not sure whether this is the right path to pursue.
DECLARE @XmlFile XML =
'<?xml version="1.0" encoding="utf-8"?>
<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>
<Account_GetDataArrayResponse xmlns="http://e-conomic.com">
<Account_GetDataArrayResult>
<AccountData>
<Handle>
<Number>1000</Number>
</Handle>
<Number>1000</Number>
<Name>RESULTATOPGØRELSE</Name>
<Type>Heading</Type>
<DebitCredit>Debit</DebitCredit>
<IsAccessible>true</IsAccessible>
<BlockDirectEntries>false</BlockDirectEntries>
<Balance>0.00</Balance>
</AccountData>
<AccountData>
<Handle>
<Number>1001</Number>
</Handle>
<Number>1001</Number>
<Name>Omsætning</Name>
<Type>Heading</Type>
<DebitCredit>Debit</DebitCredit>
<IsAccessible>true</IsAccessible>
<BlockDirectEntries>false</BlockDirectEntries>
<Balance>0.00</Balance>
</AccountData>
</Account_GetDataArrayResult>
</Account_GetDataArrayResponse>
</soap:Body>
</soap:Envelope>'
;WITH XMLNAMESPACES( 'http://www.w3.org/2001/XMLSchema' AS e)
SELECT
AccountHandleNumber = AccountData.value('(Handle/Number)[1]', 'int')
,AccountName = AccountData.value('(Name)[1]', 'varchar(20)')
,AccountNumber = AccountData.value('(Number)[1]', 'int')
,AccountType = AccountData.value('(Type)[1]','varchar(20)')
,AccountDebitCredit = AccountData.value('(DebitCredit)[1]', 'varchar(20)')
,AccountIsAccessible = AccountData.value('(IsAccessible)[1]', 'varchar(20)')
,AccountBlockDirectEntries = AccountData.value('(BlockDirectEntries)[1]', 'varchar(20)')
,AccountBalance = AccountData.value('(Balance)[1]', 'float')
FROM @XMLFile.nodes('/Account_GetDataArrayResponse/Account_GetDataArrayResult/AccountData') AS XTbl(AccountData)
Upvotes: 1
Views: 46
Reputation: 754298
Yes, this is very much the right way!
However, you're not reading the entire XML you have - you have to really start at the root node - so try to adapt your code like this:
;WITH XMLNAMESPACES('http://schemas.xmlsoap.org/soap/envelope/' AS e,
DEFAULT 'http://e-conomic.com')
SELECT
AccountHandleNumber = AccountData.value('(Handle/Number)[1]', 'int')
.....
FROM
@XMLFile.nodes('/e:Envelope/e:Body/Account_GetDataArrayResponse/Account_GetDataArrayResult/AccountData') AS XTbl(AccountData)
First of all - you need to also take care of the <soap:Envelope>
and <soap:Body>
tags at the very beginning of the document - you've created a XML namespace alias of e
for that - so you need to include /e:Envelope/e:Body
at the beginning of your XPath expression in the .nodes()
call.
Also: the <Account_GetDataArrayResponse>
node declares another XML namespace which gets applied throughout the rest of the XML document - I've added that as the DEFAULT
XML namespace to the query, so it will be applied to any node in the XPath expression that doesn't have an explicit XML namespace prefix associated with it
Upvotes: 1