【问题标题】:Getting data from poorly structured xml from sql server 2014从 sql server 2014 结构不良的 xml 获取数据
【发布时间】:2017-10-23 17:19:03
【问题描述】:

您好,我有一个新手问题,抱歉。

我必须使用设计愚蠢的 XML 格式 将对象属性数据作为标签提供,其中 标记值更改它意味着一个属性。 未提供属性的地方,例如。哺乳动物,这意味着 值未知。

以以下为例: 第三级标签可以是 20 个不同的值之一。 第四级标签(哺乳动物)可以是几个值之一,并且 可能不存在。

如何编写 XQuery 命令以超越 未知/缺少标签?

选择 t.c.value('v[1]', 'varchar(100)') 作为动物 从@xml.nodes('/recs/rec//a1// as t.c

declare @xml xml =
'
<recs>
        <rec>
        <a>
            <a1>
                <mammal>
                    <v>dog</v>
                </mammal>
            </a1>
        </a>
    </rec>
    <rec>
        <b>
            <a1>
                <mammal>
                    <v>cat</v>
                </mammal>
            </a1>
        </b>
    </rec>
    <rec>
        <b>
            <a1>
                <v>pig</v>
            </a1>
        </b>
    </rec>
</recs>'

谢谢

【问题讨论】:

  • 不清楚你在问什么。 “超越”是什么意思?你的意思是你想选择所有第五级元素而不考虑它们的父元素的名称吗? /*/*/*/*/* 可以做到这一点。
  • 是的,如果父元素的名称一致,我就可以编写查询来获取它们。我的示例仅显示了两个名称,但可能有数百个。

标签: sql-server xml xquery


【解决方案1】:

要检索第五层的所有元素,请使用

/*/*/*/*/*

在您显示的输入中,这将检索两个mammal 元素和一个pig。 (你说mammal 在第四级;似乎从零开始计数;我从一开始计数。)如果您想要他们的孩子,请添加/*

如果您只需要特定上下文中的五级或六级元素,您当然可以将星号替换为更具限制性的内容:

/recs/rec/b/a1/*

第五级,和

/recs/rec/b/a1/*/*

第六个。

【讨论】:

  • 如何获得实际的标签值,即。 a1 还是哺乳动物?选择 Tab.Col.value('../v[1]', 'varchar(10)') 作为动物 ,Tab.Col.value('v[1]', 'varchar(10)') 作为动物 FROM @xml.nodes('/recs/rec/*/a1/*') Tab(Col)
  • 阅读 XPath 教程;使用name() 来获取元素名称(我假设您所说的“实际标签值”是指您的意思,尽管它不是 XDM 中的“值”)。
  • @Shnugo - 你可能是对的。由于 OP 对所需元素的唯一了解是它们处于第 n 级,因此我不知道如何在不计算级别的情况下获得它们。我的注意力集中在表面上看起来是 OP 关于 XQuery(或者,严格来说,XPath)的问题上。如果 SQL Server 的 SQL 和 XQuery 组合中有一些工具可以提供更好的解决方案,那我很好。
  • 是的,你可能也是对的,删除了我的评论...抱歉吠叫:-D 再次阅读问题后,我认为我们的两个答案都不能完全满足需求。投票给你
  • 我刚刚更新了我的答案以满足需求 - 希望
【解决方案2】:

不,你不需要计算级别并结合*的正确计数

试试这个,它使用深度搜索//

SELECT any_v.value('text()[1]','nvarchar(max)') AS TheTextWithinV
      ,any_v.value('local-name(..)','nvarchar(max)') AS TheNameOfTheParent
FROM @xml.nodes('//v') AS DeepSearch(any_v);

您应该尽可能具体我建议在.nodes()

FROM @xml.nodes('/recs/rec//v') AS DeepSearch(any_v);

它将沿着路径向下直到&lt;rec&gt;,然后进行深度搜索直到&lt;v&gt;

由于在任何地方都没有其他text(),您甚至可以这样做:

SELECT any_v.value('.','nvarchar(max)') AS FirstTextFound
FROM @xml.nodes('/recs/rec') AS DeepSearch(any_v);

更新另一种方法

试试这个

SELECT r.value('local-name(.)','nvarchar(max)') AS Level2
      ,r.value('local-name((./*)[1])','nvarchar(max)') AS Level3
      ,r.value('if(local-name((./*/*)[1])="v") then "" else local-name((./*/*)[1])','nvarchar(max)') AS Level4
      ,r.value('(.//v/text())[1]','nvarchar(max)') AS Level5
FROM  @xml.nodes('/recs/rec/*') AS A(r);

得到这个

Level2  Level3  Level4  Level5
a       a1      mammal  dog
b       a1      mammal  cat
b       a1              pig

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-12-25
    • 2021-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-31
    • 1970-01-01
    • 2017-10-22
    相关资源
    最近更新 更多