从具有多个名称空间的XML中选择值

时间:2017-12-15 09:29:27

标签: sql sql-server xml

我需要从XML列中读取属性的值。数据是一个声明了多个名称空间的XML:

<sd:objectData xmlns:sd="http://sd-uri">
    <sd:object sourceKey="FC5A0A51-7FB6-4C64-A13E-D4B00649E80E">
        <do:properties xmlns:do="http://do-uri">
            <do:property name="DECISION">
                <do:propertyValues clearExistingValues="true">
                    <do:propertyValue action="add" valueInteger="1000142" tag="Approve" />
                </do:propertyValues>
            </do:property>
        </do:properties>
    </sd:object>
</sd:objectData>

我想读取valueInteger的值,即在此示例1000142中。我尝试使用WITH XMLNAMESPACES(),但我无法将它们组合在一起来定义两个别名。

2 个答案:

答案 0 :(得分:3)

这对你有用吗?

DECLARE @XML xml = '
<sd:objectData xmlns:sd="http://sd-uri">
    <sd:object sourceKey="FC5A0A51-7FB6-4C64-A13E-D4B00649E80E">
        <do:properties xmlns:do="http://do-uri">
            <do:property name="DECISION">
                <do:propertyValues clearExistingValues="true">
                    <do:propertyValue action="add" valueInteger="1000142" tag="Approve" />
                </do:propertyValues>
            </do:property>
        </do:properties>
    </sd:object>
</sd:objectData>';

WITH XMLNAMESPACES ('http://sd-uri' AS sd,
                    'http://do-uri' AS do)
SELECT @XML.value('(/sd:objectData/sd:object/do:properties/do:property/do:propertyValues/do:propertyValue/@valueInteger)[1]','int') AS valueInteger;

答案 1 :(得分:2)

除了Larnu的答案(这是最好和正确的答案)之外,还有一些替代的快捷方式,如果您只想获得一个值:

此查询以四种不同的方法获取所需的值

SELECT @XML.value(N'(//*/@valueInteger)[1]',N'int') AS Super_easy_with_double_wildcard
      ,@XML.value(N'(//*:propertyValue/@valueInteger)[1]',N'int') AS Easy_with_namespace_wildcard
      ,@XML.value(N'declare namespace do="http://do-uri";
                    (//do:propertyValue/@valueInteger)[1]',N'int') AS with_local_declaration
      ,@XML.value(N'declare namespace do="http://do-uri";
                    declare namespace sd="http://sd-uri";
                    (/sd:objectData/sd:object/do:properties/do:property/do:propertyValues/do:propertyValue/@valueInteger)[1]',N'int') AS with_full_local_declaration;

一般建议是:尽量避免使用hassel 。如果你不打扰,只需要一个可读的,快速的捕获,你可以采取其中一种选择。

更新添加谓词

使用谓词,您可以放置​​过滤器:

SELECT @XML.value(N'(//*:property[@name="DECISION"]//*:propertyValue/@valueInteger)[1]',N'int') AS Example_with_predicate