我有一堆XML需要用SQL解析。
XML可以采用多种形式:
<Grandparent>
<parent>
<child1>something</child1>
<child2>something</child2>
</parent>
</Grandparent>
或
<Grandparent>
<child1>something</child1>
<child2>something</child2>
</Grandparent>
此外,&#34;孩子的数量&#34;节点是可变的,没有办法知道手头有多少孩子。
到目前为止,我所做的是:
@xml.nodes('/Grandparent')
返回<parent>
节点和子节点,或仅返回child
节点,具体取决于xml的格式。
SQL的版本以及我将其编写为SQL函数这一事实似乎意味着尝试按this anwser中所示的value
进行操作不起作用。
因此,我决定解析字符串。基本上,我查找<
并从那里获取子字符串,直到>
为节点名称。然后我在>
和</
之间取值。我在while循环中执行此操作,直到xml字符串完成。除非xml具有parent
节点,否则它完美地工作。
我不知道如何确定parent
节点是否存在以及如何忽略它。这就是我被困住的地方。
在任何一种情况下我想得到的是:
Node | Value
child1 | something
child2 | something
等等有很多子节点。
答案 0 :(得分:0)
带着两个假设离开这里;你的问题不清楚如下:
如果其中任何一个假设不正确,这个答案将无济于事:)
DECLARE @xml XML = '<Grandparent>
<parent>
<child>something</child>
<child>something</child>
</parent>
</Grandparent>'
SELECT x.value('.[1]', 'varchar(100)')
FROM @xml.nodes('/Grandparent//child') t(x)
SET @xml= '<Grandparent>
<child>something</child>
<child>something</child>
</Grandparent>'
SELECT x.value('.[1]', 'varchar(100)')
FROM @xml.nodes('/Grandparent//child') t(x)
答案 1 :(得分:0)
您可以使用后代轴//
来获取父节点内任何级别深度的子节点。
此任务的另一个有用的xpath语法是local-name()
,它返回当前上下文节点/属性的名称而没有名称空间:
select c.value('local-name(.)', 'varchar(max)') as 'node'
, c.value('.', 'varchar(max)') as 'value'
from @xml.nodes('/Grandparent//*[not(*)]') as T(c)
此xpath位//*[not(*)]
表示没有子节点的选择后代节点,换句话说,选择最内层的后代。
<强> SQL Fiddle 强>
答案 2 :(得分:0)
尝试:
DECLARE @xml xml = N'
<Grandparent>
<parent>
<child1>something</child1>
<child2>something</child2>
</parent>
</Grandparent>';
SELECT
child.value('fn:local-name(.)', 'varchar(100)') AS Node
,child.value('.', 'varchar(100)') AS value
FROM @xml.nodes('//*[self::child1 or self::child2]') AS ansestor(child);
SET @xml = N'
<Grandparent>
<child1>something</child1>
<child2>something</child2>
</Grandparent>';
SELECT
child.value('fn:local-name(.)', 'varchar(100)') AS Node
,child.value('.', 'varchar(100)') AS value
FROM @xml.nodes('//*[self::child1 or self::child2]') AS ansestor(child);