SQL Server Parse XML空属性

时间:2012-11-12 00:57:00

标签: xml sql-server-2008 tsql xquery

我正在尝试通过TSQL在sql server 2008中解析/粉碎XML,其中一个节点具有以下格式的空白属性,没有指定值。我似乎无法检索该值,它会抛弃所有其他值(移动列?)

这是tsql代码和错误的图片:

declare @doc nvarchar(4000)

set @doc = ' 
<Objects>
  <Object>
    <Property Name="Path">some path</Property>
    <Property Name="InstanceName">some instance</Property>
    <Property Name="result1">0.390630000000003</Property>
    <Property Name="result2">63345649697265</Property>
  </Object>
  <Object>
    <Property Name="Path">another path</Property>
    <Property Name="InstanceName" />
    <Property Name="result1">100</Property>
    <Property Name="result2">1002</Property>
  </Object>
 </Objects>
'
  SELECT 
 item.ref.value('(Property/text())[1]', 'nvarchar(128)') AS Path, 
 item.ref.value('(Property/text())[2]', 'nvarchar(128)') AS InstanceName,
 item.ref.value('(Property/text())[3]', 'nvarchar(128)') AS result1,
 item.ref.value('(Property/text())[4]', 'nvarchar(128)') AS result2
  FROM (SELECT CAST(@doc AS XML) AS feedXml) feeds(feedXml) 
   CROSS APPLY feedXml.nodes('/Objects/Object') AS item(ref)

当您运行查询通知时,将使用其他列中的值填充InstanceName列而不是空白,空或null。

感谢任何帮助。

2 个答案:

答案 0 :(得分:2)

您需要使用<Property>属性引用这些Name元素 - 而不仅仅是索引!

试试这个:

SELECT
    item.ref.value('(Property[@Name="Path"]/text())[1]', 'nvarchar(128)') AS Path,
    item.ref.value('(Property[@Name="InstanceName"]/text())[1]', 'nvarchar(128)') AS InstanceName,
    item.ref.value('(Property[@Name="result1"]/text())[1]', 'nvarchar(128)') AS result1,
    item.ref.value('(Property[@Name="result2"]/text())[1]', 'nvarchar(128)') AS result2
FROM 
    (SELECT CAST(@doc AS XML) AS feedXml) feeds(feedXml) 
CROSS APPLY 
    feedXml.nodes('/Objects/Object') AS item(ref)

有了这个,您应该将第二个InstanceName作为NULL

答案 1 :(得分:1)

在括号内指定您想要的节点,因此[4]表示您想要第四行。您使用的XPath表达式为Property/text(),这意味着'(Property/text())[4]'将为您提供第四个文本值。您的第二个对象只有三个文本值,这就是您的值关闭的原因 相反,您可以指定您希望第四个属性节点'(Property[4]/text())[1]'中的第一个文本值。

完整查询可能如下所示:

SELECT 
 item.ref.value('(Property[1]/text())[1]', 'nvarchar(128)') AS Path, 
 item.ref.value('(Property[2]/text())[1]', 'nvarchar(128)') AS InstanceName,
 item.ref.value('(Property[3]/text())[1]', 'nvarchar(128)') AS result1,
 item.ref.value('(Property[4]/text())[1]', 'nvarchar(128)') AS result2
  FROM (SELECT CAST(@doc AS XML) AS feedXml) feeds(feedXml) 
   CROSS APPLY feedXml.nodes('/Objects/Object') AS item(ref)

如果您缺少属性节点或者节点的顺序不一致,上述情况当然仍会失败。在这种情况下,您应该使用查询provided by marc_s