Elad L.
Elad L.

Reputation: 639

parsing XML with SQL

i have this xml:

<workbook>
 <datasources>
    <datasource>
        <connection>
            <relation name='table_1'/>
            <metadata-records class='column'>
                <metadata-record>
                    <remote-name>a1</remote-name>
                    <parent-name>aa1</parent-name>
                </metadata-record>
            </metadata-records>
            <metadata-records class='column'>
                <metadata-record>
                    <remote-name>b1</remote-name>
                    <parent-name>bb1</parent-name>
                </metadata-record>
            </metadata-records>
            <metadata-records class='column'>
                <metadata-record>
                    <remote-name>c1</remote-name>
                    <parent-name>cc1</parent-name>
                </metadata-record>
            </metadata-records>
        </connection>
    </datasource>
    <datasource>
        <connection>
            <relation name='table_2'/>
            <metadata-records class='column'>
                <metadata-record>
                    <remote-name>a2</remote-name>
                    <parent-name>aa2</parent-name>
                </metadata-record>
            </metadata-records>
            <metadata-records class='column'>
                <metadata-record>
                    <remote-name>b2</remote-name>
                    <parent-name>bb2</parent-name>
                </metadata-record>
            </metadata-records>
            <metadata-records class='column'>
                <metadata-record>
                    <remote-name>c2</remote-name>
                    <parent-name>cc2</parent-name>
                </metadata-record>
            </metadata-records>
        </connection>
    </datasource>
  </datasources>
</workbook>

im trying to parse it in SQL so i would get this table:

relation remote-name parent-name
-------- ----------- -----------
table_1  a1          aa1
table_1  b1          bb1
table_1  c1          cc1
table_2  a2          aa2
table_2  b2          bb2
table_2  c2          cc2

i used a few queries and I'm getting too many errors. i think I'm missing something in my basic understanding of XML parsing via SQL.

if you can either help me figure this out or help me find a proper place to learn this that will be great.

thanks.

this is the query I'm executing:

select 
    temp.relation.value('(//relation/@name)[1]','nvarchar(100)')as [relation]
    ,temp.relation.value('(//metadata-records/metadata-record/remote-name)[1]','nvarchar(100)')
    ,temp.relation.value('(//metadata-records/metadata-record/parent-name)[1]','nvarchar(100)')
from
(select 
    c1.query('..') as relation
from 
    tempXml
    cross apply twb.nodes('/workbook/datasources/datasource/connection') as T1(c1)) as temp

Upvotes: 0

Views: 69

Answers (1)

GarethD
GarethD

Reputation: 69769

You need to apply a further nodes function to split each relation into its nodes:

SELECT  relation = t1.c1.value('(relation/@name)[1]', 'NVARCHAR(MAX)'),
        [remote-name] = c2.value('remote-name[1]', 'NVARCHAR(MAX)'),
        [parent-name] = c2.value('parent-name[1]', 'NVARCHAR(MAX)')
FROM    tempXml AS tmp
        CROSS APPLY tmp.twb.nodes('/workbook/datasources/datasource/connection') AS t1 (c1)
        CROSS APPLY t1.c1.nodes('metadata-records/metadata-record') AS t2 (c2);

FULL WORKING EXAMPLE

DECLARE @XML XML = '<workbook>
 <datasources>
    <datasource>
        <connection>
            <relation name="table_1"/>
            <metadata-records class="column">
                <metadata-record>
                    <remote-name>a1</remote-name>
                    <parent-name>aa1</parent-name>
                </metadata-record>
            </metadata-records>
            <metadata-records class="column">
                <metadata-record>
                    <remote-name>b1</remote-name>
                    <parent-name>bb1</parent-name>
                </metadata-record>
            </metadata-records>
            <metadata-records class="column">
                <metadata-record>
                    <remote-name>c1</remote-name>
                    <parent-name>cc1</parent-name>
                </metadata-record>
            </metadata-records>
        </connection>
    </datasource>
    <datasource>
        <connection>
            <relation name="table_2"/>
            <metadata-records class="column">
                <metadata-record>
                    <remote-name>a2</remote-name>
                    <parent-name>aa2</parent-name>
                </metadata-record>
            </metadata-records>
            <metadata-records class="column">
                <metadata-record>
                    <remote-name>b2</remote-name>
                    <parent-name>bb2</parent-name>
                </metadata-record>
            </metadata-records>
            <metadata-records class="column">
                <metadata-record>
                    <remote-name>c2</remote-name>
                    <parent-name>cc2</parent-name>
                </metadata-record>
            </metadata-records>
        </connection>
    </datasource>
  </datasources>
</workbook>';

SELECT  relation = t1.c1.value('(relation/@name)[1]', 'NVARCHAR(MAX)'),
        [remote-name] = c2.value('remote-name[1]', 'NVARCHAR(MAX)'),
        [parent-name] = c2.value('parent-name[1]', 'NVARCHAR(MAX)')
FROM    @XML.nodes('/workbook/datasources/datasource/connection') AS t1 (c1)
        CROSS APPLY t1.c1.nodes('metadata-records/metadata-record') AS t2 (c2);

Upvotes: 2

Related Questions