【问题标题】:How to get value from a node in XML via SQL Server如何通过 SQL Server 从 XML 中的节点获取值
【发布时间】:2018-12-07 17:19:33
【问题描述】:

我在网上找到了几条关于此的信息,但我无法让它终生发挥作用。

这是我拥有的 XML:

我需要提取每个节点的 ID 和名称值。有很多。

我尝试这样做,但它返回 NULL:

select [xml].value('(/Alter/Object/ObjectDefinition/MeasureGroup/Partitions/Partition/ID)[1]', 'varchar(max)')
from test_xml

我知道上面只会返回 1 条记录。我的问题是,如何返回所有记录?

这是 XML 文本(精简版):

<Alter xmlns="http://schemas.microsoft.com/analysisservices/2003/engine" AllowCreate="true" ObjectExpansion="ExpandFull">
  <ObjectDefinition>
    <MeasureGroup xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <ID>ts_homevideo_sum_20140430_76091ba1-3a51-45bf-a767-f9f3de7eeabe</ID>
      <Name>table_1</Name>
      <StorageMode valuens="ddl200_200">InMemory</StorageMode>
      <ProcessingMode>Regular</ProcessingMode>
      <Partitions>
        <Partition>
          <ID>123</ID>
          <Name>2012</Name>
        </Partition>
        <Partition>
          <ID>456</ID>
          <Name>2013</Name>
        </Partition>
      </Partitions>
    </MeasureGroup>
  </ObjectDefinition>
</Alter>

【问题讨论】:

  • 这个命名空间的东西是我仍在努力学习和理解的东西,也许其他人可以给出一个有效的答案并有希望地解释它。如果我找到一种方法来完成这项工作,我会发布一个新的答案。
  • 不用担心。感谢您的尝试!
  • 不客气。抱歉,我无法提供更多帮助

标签: sql sql-server xml xquery


【解决方案1】:

你需要这样的东西:

DECLARE @MyTable TABLE (ID INT NOT NULL, XmlData XML)

INSERT INTO @MyTable (ID, XmlData)
VALUES (1, '<Alter xmlns="http://schemas.microsoft.com/analysisservices/2003/engine" AllowCreate="true" ObjectExpansion="ExpandFull">
  <ObjectDefinition>
    <MeasureGroup xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <ID>ts_homevideo_sum_20140430_76091ba1-3a51-45bf-a767-f9f3de7eeabe</ID>
      <Name>table_1</Name>
      <StorageMode valuens="ddl200_200">InMemory</StorageMode>
      <ProcessingMode>Regular</ProcessingMode>
      <Partitions>
        <Partition>
          <ID>123</ID>
          <Name>2012</Name>
        </Partition>
        <Partition>
          <ID>456</ID>
          <Name>2013</Name>
        </Partition>
      </Partitions>
    </MeasureGroup>
  </ObjectDefinition>
</Alter>')

;WITH XMLNAMESPACES(DEFAULT 'http://schemas.microsoft.com/analysisservices/2003/engine')
SELECT 
    tbl.ID,
    MeasureGroupID = xc.value('(ID)[1]', 'varchar(200)'),
    MeasureGroupName = xc.value('(Name)[1]', 'varchar(200)'),
    PartitionID = xp.value('(ID)[1]', 'varchar(200)'),
    PartitionName = xp.value('(Name)[1]', 'varchar(200)')
FROM
    @MyTable tbl
CROSS APPLY
    tbl.XmlData.nodes('/Alter/ObjectDefinition/MeasureGroup') AS XT(XC)
CROSS APPLY
    XC.nodes('Partitions/Partition') AS XT2(XP)
WHERE   
    ID = 1

首先,您必须尊重并包含定义在 XML 文档根目录中的默认 XML 命名空间

接下来,您需要对.nodes() 进行嵌套调用以获取所有&lt;MeasureGroup&gt; 和所有包含的&lt;Partition&gt; 节点,以便您可以访问这些XML 片段并从中提取IDName他们。

这应该会产生类似这样的输出:

【讨论】:

  • 我自己正在尝试更好地理解这一点,为什么您不必将其添加到 XMLNAMESPACES xmlns:xsd="http://www.w3.org/2001/XMLSchema"??是因为 xsd 已经声明了吗?
  • 谢谢你,Marc_s!这成功了。虽然我不得不删除 tbl.ID / ID = 1 部分。
  • @marc_s 节点分区和分区是否考虑嵌套,因为 MeasureGroup 是它自己的 xml?这就是需要 CROSS APPLY 的原因吗?
  • @RyanWilson:xsd 命名空间不需要添加,因为它是 (a) 而不是 default 命名空间(XML 命名空间没有前缀),并且(b)它不在任何地方使用
  • @RyanWilson:您需要CROSS APPLY 来处理特定节点的多次出现。我不确定是否可能有多个 &lt;MeasureGroup&gt; 元素 - 示例没有显示它,但使用 CROSS APPLY,代码还可以处理具有 4 个或 5 个 &lt;MeasureGroup&gt; 节点的 XML
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-09
  • 1970-01-01
  • 2013-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多