SQL解析xml字符串

时间:2015-04-27 02:23:28

标签: sql sql-server xml parsing

我有一堆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

等等有很多子节点。

3 个答案:

答案 0 :(得分:0)

带着两个假设离开这里;你的问题不清楚如下:

  1. 我假设您的子节点具有相同的名称(例如,子节点,而不是child1和child2),并且
  2. 您需要一个每行返回1个子项的SQL语句。
  3. 如果其中任何一个假设不正确,这个答案将无济于事:)

    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);