4

I have a XML data like this :

<root>
 <log realm="ABC" at="Wed Oct 15 00:00:02 2014.211" lifespan="2279ms">
  <receive>
    <isomsg direction="IN">
      <header>6000911384</header>
      <field id="0" value="0800"/>
      <field id="3" value="980000"/>
      <field id="11" value="000852"/>
    </isomsg>
  </receive>
</log>
</root>

how can I transform that XML data into table like this :

    AT         |lifespan|direction |ID |Value 
---------------------------------------------
Wed Oct 15 2014|2279ms  |in        |0  |0800
Wed Oct 15 2014|2279ms  |in        |3  |980000
Wed Oct 15 2014|2279ms  |in        |11 |000852
2
  • 1
    Check This question Commented Oct 15, 2014 at 18:13
  • You could also look into creating an xslt to transform the data into an SQL script Commented Oct 15, 2014 at 18:19

2 Answers 2

4

This would be a lot easier than @Nick's answer, since it only needs one .nodes() call instead of three nested ones...

DECLARE @input XML = '<root>
 <log realm="ABC" at="Wed Oct 15 00:00:02 2014.211" lifespan="2279ms">
  <receive>
    <isomsg direction="IN">
      <header>6000911384</header>
      <field id="0" value="0800"/>
      <field id="3" value="980000"/>
      <field id="11" value="000852"/>
    </isomsg>
  </receive>
</log>
</root>'

SELECT
    At = xc.value('../../../@at', 'varchar(50)'),
    Lifespan = xc.value('../../../@lifespan', 'varchar(25)'),
    Direction = xc.value('../@direction', 'varchar(10)'),
    ID = XC.value('@id', 'int'),
    Value = xc.value('@value', 'varchar(25)')
FROM
    @Input.nodes('/root/log/receive/isomsg/field') AS XT(XC)

The call to @Input.nodes basically returns a "virtual" table of XML fragments, representing each of the <field> XML elements. By using the .. we can also navigate "up the" XML hierarchy in the original document to access the <isomsg> and <log> elements and grab attribute values from those

Sign up to request clarification or add additional context in comments.

2 Comments

Nice!! Way cleaner than mine. I assume this works when selecting the data from a table (opposed to a variable with XML data)? I only ask because I originally had something simliar to this but had trouble getting it to work. I started the nodes from the top level though /root/log and that could have been the issue
Wow. thats simple. Thank you very much marc_s, Thank you very much Nick
3

Here is how I did it (although there are several ways).

WITH xmlData AS (
SELECT CAST('<root>
 <log realm="ABC" at="Wed Oct 15 00:00:02 2014.211" lifespan="2279ms">
  <receive>
    <isomsg direction="IN">
      <header>6000911384</header>
      <field id="0" value="0800"/>
      <field id="3" value="980000"/>
      <field id="11" value="000852"/>
    </isomsg>
  </receive>
</log>
</root>' AS XML) as xmlData)
SELECT xmlData, logs.x.value('(@at)[1]','varchar(50)') as 'Element1', logs.x.value('(@lifespan)[1]','varchar(50)') as 'Element2', ismsgs.logs.value('(@direction)[1]','varchar(50)') as 'Element3', fields.ismsgs.value('(@value)[1]','varchar(50)') as 'Element4'
FROM xmlData x
CROSS APPLY xmlData.nodes('root/log') logs(x)   
CROSS APPLY xmlData.nodes('root/log/receive/isomsg') ismsgs(logs)
CROSS APPLY xmlData.nodes('root/log/receive/isomsg/field') fields(ismsgs)

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.