简体   繁体   中英

Get the name of tag and attribute in XML

I have to process an XML file with following format:

<Root>
<A name="x1">
    <B exp="h1", ref="r1"/>
    <C exp="h2", ref="r2", rat = "ra1"/>
    <D exp="h3", ref="r3"/>
</A>
<A name="x2">
    <E exp="h4", ref="r4"/>
    <F exp="h5", ref="r5"/>
</A>
</Root>

I want to write an stored procedure to get a table like:

|A_name|tag_name|attrbute|val|
|x1    |   B    |exp|h1|
|x1    |   B    |ref|r1|
|x1    |   C    |exp|h2|
|x1    |   C    |rat|ra1|
|x1    |   C    |ref|r2|
|x1    |   D    |exp|h3|
|x1    |   D    |ref|r3|
|x2    |   E    |exp|h4|
|x2    |   E    |ref|r4|
|x2    |   F    |exp|h5|
|x2    |   F    |ref|r5|

How can I do? I've already try

SELECT localname
FROM OPENXML(@idoc, '/A') 
WHERE localname!='A'

to get the tag name. However, I am not able to join them with attribute of tag A.

If your initial data is wrong (and the commas are not used to separate tags) you can try this:

DECLARE @XML XML = N'<Root>
<A name="x1">
    <B exp="h1" ref="r1"/>
    <C exp="h2" ref="r2" rat = "ra1"/>
    <D exp="h3" ref="r3"/>
</A>
<A name="x2">
    <E exp="h4" ref="r4"/>
    <F exp="h5" ref="r5"/>
</A>
</Root>'

SELECT [A_name]
       ,[B_name]
       ,attribute
       ,value
FROM
(
    SELECT T1.c.value('(./@name)[1]', 'varchar(12)') as [A_name]
          ,T2.c.value('local-name(.)', 'varchar(12)') as [B_name]
          ,T2.c.value('(@exp)[1]', 'varchar(30)') AS [exp]
          ,T2.c.value('(@ref)[1]', 'varchar(30)') AS [ref]
          ,T2.c.value('(@rat)[1]', 'varchar(30)') AS [rat]
    FROM @XML.nodes('Root/A') T1(c)
    CROSS APPLY T1.c.nodes('./*') T2(c)
) DS
UNPIVOT
(
    [value] for [attribute] IN ([exp], [ref], [rat])
) UNPVT;

在此处输入图像描述

Similar to gotqn's answer... you can get all of the attributes of an element by way of a @* wildcard query thus avoiding the pivot (which requires knowledge of all the attribute names ahead of time), eg:

select
  a.a.value('(@name)[1]', 'nvarchar(50)') as 'a_name',
  b.b.value('local-name(.)', 'nvarchar(50)') as 'tag_name',
  c.c.value('local-name(.)', 'nvarchar(50)') as 'attribute',
  c.c.value('data(.)', 'nvarchar(50)') as 'val'
from @example.nodes('//A') a(a)
cross apply a.a.nodes('*') b(b)
cross apply b.b.nodes('@*') c(c);
| a_name | tag_name | attribute | val |
|--------|----------|-----------|-----|
| x1     | B        | exp       | h1  |
| x1     | B        | ref       | r1  |
| x1     | C        | exp       | h2  |
| x1     | C        | ref       | r2  |
| x1     | C        | rat       | ra1 |
| x1     | D        | exp       | h3  |
| x1     | D        | ref       | r3  |
| x2     | E        | exp       | h4  |
| x2     | E        | ref       | r4  |
| x2     | F        | exp       | h5  |
| x2     | F        | ref       | r5  |

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM