2016-01-18 102 views
1

我想从SOAP API解析一些XML。我对XML非常陌生,但是只有声明的主体才能使用它。我试过应用一些简单的命名空间,但我不确定这是否是正确的追求路径。如何应用XML名称空间

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) 

回答

1

没错,这就是非常正道!

但是,你不读你拥有整个XML - 你必须真正开始根节点 - 所以尽量去适应你的代码是这样的:

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

首先的 - 你需要还要处理文档一开始的<soap:Envelope><soap:Body>标签 - 您已为此创建了一个XML名称空间别名e - 因此您需要在.nodes()调用中的XPath表达式开头处包含/e:Envelope/e:Body

另外:<Account_GetDataArrayResponse>节点声明它获取整个XML文档的其余部分用于另一个XML命名空间 - 我补充说,由于DEFAULT XML命名空间来查询,所以它会在XPath表达式可以应用于任何节点没有一个明确的XML命名空间前缀关联它

+0

非常感谢,这为我解决了不少问题。 不过,似乎有东西不能正常工作,因为我没有得到任何记录返回。查询执行但不返回任何内容。我使用正确的命名空间,有三个,但我想我要使用xmlns:? 任何帮助表示赞赏。 Rasmus –

+0

@RasmusRødbyKristiansen:是的 - 您在'WITH XMLNAMESPACES ....'标题中使用*错误* XML名称空间;您需要使用与原始XML文档中的“soap”前缀关联的那个。尝试我的更新回复 –

+0

太好了,谢谢你! 我当然需要阅读所有这些,因为我看到它的工作,但并不真正理解为什么。有一个美好的一天.. @marc_s –