1

I need to read a value of an attribute from an XML column. The data is an XML with multiple namespaces declared:

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

I want to read the value of valueInteger, namely in this example 1000142. I tried with WITH XMLNAMESPACES() but I am not able to get it together to define both aliases.

2 Answers 2

3

Does this work for you?

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;
Sign up to request clarification or add additional context in comments.

1 Comment

Correct answer, +1 from my side
2

In addition to Larnu's answer (which is the best and correct answer) just some alternative shortcuts, if you just want to get one value:

This query fetches the needed value in four different approaches

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;

The general advise is: Be as specific as possible to avoid hassels. If you do no bother and you just need a readable, quick catch, you can take one of the alternatives.

UPDATE Add a predicate

With a predicate you can place a filter:

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

1 Comment

Would it be possible to filter on the property @name attribute? The XML sample here only contains one for simplicity but the real one has some more

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.