Home Forums Programming XML XML Shred to tabular data RE: XML Shred to tabular data

  • As Jeff points out, the xml isn't ideal which is true, but I have come up with something that makes a lot of assumptions!. Mainly around the ordering of the xml which if changes, will break this so I give no assurances to this code 😀

    DECLARE @xml XML

    SET @xml = '<employees>

    <employee>

    <emp_id>1</emp_id>

    <emp_name>Bob</emp_name>

    <skills>

    <skills_id>1</skills_id>

    <skills_id>tsql</skills_id>

    <skills_id>2</skills_id>

    <skills_id>SSRS</skills_id>

    <skills_id>3</skills_id>

    <skills_id>SSAS</skills_id>

    <skills_id>4</skills_id>

    <skills_id>SSIS</skills_id>

    <skills_id>5</skills_id>

    <skills_id>Replication</skills_id>

    </skills>

    </employee>

    <employee>

    <emp_id>2</emp_id>

    <emp_name>Frank</emp_name>

    <skills>

    <skills_id>1</skills_id>

    <skills_id>tsql</skills_id>

    <skills_id>2</skills_id>

    <skills_id>SSRS</skills_id>

    <skills_id>3</skills_id>

    <skills_id>SSAS</skills_id>

    </skills>

    </employee>

    </employees>

    '

    SELECT @xml = @xml.query('

    <employees>

    {

    for $x in //employee

    return

    <employee emp_name="{$x/emp_name/text()}" emp_id="{$x/emp_id/text()}">

    {

    for $y in $x/skills/skills_id[number(text()[1]) > 0]

    return

    <skill id="{data($y)}" value="{data($x/skills/skills_id[. >> $y][1])}"/>

    }

    </employee>

    }

    </employees>

    ')

    SELECT e.c.value('@emp_id', 'int') AS emp_id

    , e.c.value('@emp_name', 'varchar(50)') AS emp_name

    , s.c.value('@id', 'int') AS skills_id

    , s.c.value('@value', 'varchar(50)') AS skill

    FROM @xml.nodes('/employees/employee') e(c)

    CROSS APPLY e.c.nodes('skill') AS s(c)

    Returns:

    emp_idemp_nameskills_idskill

    1Bob1tsql

    1Bob2SSRS

    1Bob3SSAS

    1Bob4SSIS

    1Bob5Replication

    2Frank1tsql

    2Frank2SSRS

    2Frank3SSAS