我正在尝试解析以下xml,以获取s:Body标记之后的第一个标记(在这种情况下,我正在寻找字符串queryEE
,在其他具有相同Envelope / Body结构的消息中会有所不同
我开始玩类似这样的游戏:
declare @text varchar(max)
set @text = N'
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<queryEE xmlns="http://xx.gob.gcaba.xx/">
<codeEE xmlns="">xxxx</codeEE>
</queryEE>
</s:Body>
</s:Envelope>'
declare @x xml
set @x = cast(@text as xml)
select @x.query('/s:Envelope')
但是我得到了错误:
Msg 2229, Level 16, State 1, Line 16
XQuery [query()]: The name "s" does not denote a namespace.
好像我遇到了名称空间问题
当我尝试使用select @x.query('/Envelope')
时,我什么都没有得到
由于我从@shnugo得到的答案,我终于可以用以下方法解决它:
select @x.value('local-name((/*:Envelope/*:Body/*)[1])','nvarchar(100)')
答案 0 :(得分:1)
在将xquery用于具有命名空间的xml时,再次声明您的命名空间。
declare @text varchar(max)
set @text = N'
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<queryEE xmlns="http://xx.gob.gcaba.xx/">
<codeEE xmlns="">xxxx</codeEE>
</queryEE>
</s:Body>
</s:Envelope>'
declare @x xml
set @x = cast(@text as xml)
select @x.query('declare default element namespace "http://schemas.xmlsoap.org/soap/envelope/";
/Envelope')
答案 1 :(得分:1)
像这样尝试:
-您的声明
declare @text varchar(max)
set @text = N'
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<queryEE xmlns="http://xx.gob.gcaba.xx/">
<codeEE xmlns="">xxxx</codeEE>
</queryEE>
</s:Body>
</s:Envelope>'
declare @x xml
set @x = cast(@text as xml);
-查询
WITH XMLNAMESPACES('http://schemas.xmlsoap.org/soap/envelope/' AS s
,'http://xx.gob.gcaba.xx/' AS innerDflt)
select @x.value('(/s:Envelope/s:Body/innerDflt:queryEE/codeEE/text())[1]','nvarchar(100)');
一些背景:
您看XML的命名空间有点奇怪...如果构造在您的控制之下,那么值得从这里开始。
有一个命名空间s:
用于定义<Envelope>
和<Body>
。到目前为止还好。但是元素<queryEE>
定义了一个默认名称空间(没有前缀!),而嵌入式<codeEE>
定义了另一个(但为空!)默认名称空间。我很确定,这个空的名称空间是在查询中通过将XML组合在一起而创建的。
默认名称空间告诉引擎,所有没有特定前缀的节点都位于该名称空间内。所以我们必须解决这个问题。
我的代码使用WITH XMLNAMESPACES
声明XML中出现的所有名称空间。与原始XML不同,我为第一个defualt命名空间定义了前缀(innerDflt
)。也就是说,我们可以寻址<innerDflt:queryEE>
。嵌入式元素不需要名称空间。它位于一个空的默认(=>否)命名空间中。
所有这些,我只想指出,您也可以使用通配符:
select @x.value('(/*:Envelope/*:Body/*:queryEE/*:codeEE/text())[1]','nvarchar(100)')
您甚至可以使用深度搜索
select @x.value('(//*:codeEE/text())[1]','nvarchar(100)')
但一般建议是:尽可能具体。