简体   繁体   中英

How to apply XML Namespaces

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)

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM