从 XML 列中选择所有 XML 节点

Liu*_*lis 2 xml t-sql sql-server xquery sql-server-2016

我有一个带有 XML 列的表。每个条目的 XML 结构都是完全扁平的,甚至没有父标签 - 这是一个条目的示例:

<tag1>1.22</tag1>
<tag3>5</tag3>
<tag12>-1.22</tag>
Run Code Online (Sandbox Code Playgroud)

到目前为止,我已经能够做这样的事情:

SELECT CAST(xml_column AS NVARCHAR(MAX)) as XML_text
Run Code Online (Sandbox Code Playgroud)

并在我这边解析 XML。或者我显然可以编写xpath查询来将标签选择到列中,这就是我想要的,除了大约有 1000 个可能的标签名称,而且我不想将它们全部写出来(并且可能会错过一个)。

简而言之,我该如何处理:

| ID | XML type column                |
| 1  | <tag1>1</tag1><tag2>2</tag2>   |
| 2  | <tag2>8</tag2><tag34>1</tag34> |
Run Code Online (Sandbox Code Playgroud)

对此:

| ID | tag1 | tag2 | tag34 |
| 1  | 1    | 2    | NULL  |
| 2  | NULL | 8    | 1     |
Run Code Online (Sandbox Code Playgroud)

对于我可以在数据集中找到的任何标签,而无需提前知道它们?我也愿意解决这个问题:

| ID | tag   | value | 
| 1  | tag1  | 1     |
| 1  | tag2  | 2     |
| 2  | tag2  | 8     |
| 2  | tag34 | 1     |
Run Code Online (Sandbox Code Playgroud)

Shn*_*ugo 6

以下代码会将没有根节点的平面 XML转换为经典的 EAV 列表:

DECLARE @tbl TABLE(ID INT IDENTITY, YourXml XML);
INSERT INTO @tbl VALUES
 ('<tag1>1</tag1><tag2>2</tag2>')
,('<tag3>3</tag3><tag4>4</tag4><tag5>5</tag5>');
Run Code Online (Sandbox Code Playgroud)

--查询

SELECT t.ID
      ,AllNodes.value('local-name(.)','nvarchar(max)') AS TagName
      ,AllNodes.value('text()[1]','nvarchar(max)') AS TagValue
FROM @tbl t
CROSS APPLY t.YourXml.nodes('/*') A(AllNodes);
Run Code Online (Sandbox Code Playgroud)

XQuery 函数local-name()允许查询元数据,text()节点代表元素的内容。