0

How do I extract the value of the attribute from the XML data?

drop table #demo2
create table #demo2 (field1 xml)
insert into #demo2 (field1) 
values (
'<root xmlns="system/schema" vesion="1.0">
    <header msgtype="1">
        <msgid>1</msgid>
    </header>
    <transaction>
        <systemevent>
            <eventdetail eventtype="100">
                <eventstamp unitid="87888" value="2021-11-14T01:44:41.069Z" />
                <eventitem id="1" value="abc123" />
            </eventdetail>
            <eventdetail eventtype="102">
                <eventstamp unitid="87889" value="2021-11-14T01:44:41.704Z" />
                <eventitem id="2" />
            </eventdetail>
        </systemevent>
    </transaction>
</root>')

I am expecting the answer to be abc123 & null for this XML. Below is the query I tried to get my expected value.

select  x.v.value('@value','VARCHAR(100)') AS EventValue,
        y.v.value('@value','VARCHAR(100)') AS EventValue2
from #demo2 t
cross apply field1.nodes('//eventdetail[@eventtype="100"]/eventitem') x(v)
cross apply field1.nodes('//eventdetail[@eventtype="102"]/eventitem') y(v)

I am not sure what is missing in my xpath to get the value. Thanks for your help.

1 Answer 1

4

This:

<root xmlns="system/schema" vesion="1.0">

means that the document has a default namespace, and so all the elements are actually in the namespace. That document is equivilent to this one:

<foo:root xmlns:foo="system/schema" vesion="1.0">
  <foo:header msgtype="1">
    <foo:msgid>1</foo:msgid>
  </foo:header>
  <foo:transaction>
    <foo:systemevent>
      <foo:eventdetail eventtype="100">
        <foo:eventstamp unitid="87888" value="2021-11-14T01:44:41.069Z" />
        <foo:eventitem id="1" value="abc123" />
      </foo:eventdetail>
      <foo:eventdetail eventtype="102">
        <foo:eventstamp unitid="87889" value="2021-11-14T01:44:41.704Z" />
        <foo:eventitem id="2" />
      </foo:eventdetail>
    </foo:systemevent>
  </foo:transaction>
</foo:root>

so you must namespace-qualify your query with WITH XMLNAMESPACES, eg

WITH XMLNAMESPACES (DEFAULT 'system/schema')  
select  x.v.value('@value','VARCHAR(100)') AS EventValue,
        y.v.value('@value','VARCHAR(100)') AS EventValue2
from #demo2 t
cross apply field1.nodes('//eventdetail[@eventtype="100"]/eventitem') x(v)
cross apply field1.nodes('//eventdetail[@eventtype="102"]/eventitem') y(v)

And you should also fully-qualify the element XPath instead of using // in most cases. EG

WITH XMLNAMESPACES (DEFAULT 'system/schema')  
select  x.v.value('@value','VARCHAR(100)') AS EventValue,
        y.v.value('@value','VARCHAR(100)') AS EventValue2
from #demo2 t
cross apply field1.nodes('/root/transaction/systemevent/eventdetail[@eventtype="100"]/eventitem') x(v)
cross apply field1.nodes('/root/transaction/systemevent/eventdetail[@eventtype="102"]/eventitem') y(v)
Sign up to request clarification or add additional context in comments.

Comments

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.