在T-SQL查询中,需要仅为根元素获取属性名称 - 值对

时间:2013-06-13 17:24:25

标签: sql sql-server xml tsql

我已经创建了一个表值函数,它根据Ben Davis的出色响应here返回一个属性名称 - 值对的列表,当提供XML片段时。它工作,但返回整个片段中所有属性名称 - 值对的列表,当我想将它限制在根元素上的那些时。我怎样才能做到这一点?谢谢你,来自XQuery新手。

INSERT INTO @attributeList
SELECT DISTINCT
    CAST(attribute.name.query('local-name(.)') AS VARCHAR(100)),
    attribute.name.value('.','NVARCHAR(MAX)')
FROM @xml.nodes('//@*') attribute(name)

ETA:经过一些实验后,选择器'node()/ @ *'正常工作。感谢那些帮助过的人。

我在一个简单的数据迁移应用程序或数据泵前端Sitecore中使用它。我编写了一个可以在.NET中使用POCO对象并将它们导入Sitecore的实用程序,但现在构建了一个迁移和日志记录数据库。源对象作为XML存储在一个位置。再次感谢你。

1 个答案:

答案 0 :(得分:2)

这个问题已经在评论中得到了回答,所以这只是一个有点解释的汇编。

对于实验,我们将使用此XML:

DECLARE @XML XML =
'<root root_attr="0">
   <leaf leaf_attr="1">one</leaf>
   <brunch brunch_attr="2">
     <leaf leaf_attr="3">three</leaf>
   </brunch>
</root>';

我们需要提取根元素属性列表:root_attr="0"

对于XPath参考,我们引用MSDN XPath Syntax guide

所以,&#34; /&#34;代表&#34;孩子&#34;或&#34;根节点&#34;如果出现在模式的开头,&#34; @&#34;代表&#34;属性&#34;,&#34; *&#34;代表&#34;任何&#34;和&#34;。&#34;代表&#34;当前背景&#34;。当然,这应该给我们所有的根属性:

SELECT
    CAST(attribute.name.query('local-name(.)') AS VARCHAR(MAX)) As [Name],
    attribute.name.value('.','NVARCHAR(MAX)') As [Value]
FROM @XML.nodes('/@*') attribute(name);

相反,它会出错:不支持顶级属性节点。 XML中有两种类型的节点:&lt; 元素&gt;元素值&lt; / element&gt;和&lt; element 属性 =&#34;属性值&#34; /取代。因此,/@* XPath被解释为 XML的根,而不是 根元素。事实上,可以用:

来说明
SELECT
    CAST(attribute.name.query('local-name(.)') AS VARCHAR(MAX)) As [Name],
    attribute.name.value('.','NVARCHAR(MAX)') As [Value]
FROM @XML.nodes('/') attribute(name);

返回:

Name Value
---- --------
     onethree

这是表示整个XML文档的匿名节点。 '.' XPath会给出相同的结果。

好的,我们需要在XML文档的根目录中指定任何元素。它的语法应该是&#34; //&#34; (匿名根节点的子节点=根元素)该表达式不应代表&#34;递归下降&#34; (所有孩子)。确实

SELECT
    CAST(attribute.name.query('local-name(.)') AS VARCHAR(MAX)) As [Name],
    attribute.name.value('.','NVARCHAR(MAX)') As [Value]
FROM @XML.nodes('//@*') attribute(name);

返回所有元素的完整属性列表:

Name        Value
----------- --------
root_attr   0
leaf_attr   1
brunch_attr 2
leaf_attr   3

好的,现在我们需要一种方法来说明XPath&#34; root&#34; &#34;元件&#34;而不是&#34; rootelement&#34;这显然是一个保留字。一种方法是挤入&#34;任何&#34;,另一种 - 指定它应该是&#34; node()&#34;除非我们知道根元素的实际名称。

对于给定的XML,这三者是相同的:

SELECT
    CAST(attribute.name.query('local-name(.)') AS VARCHAR(MAX)) As [Name],
    attribute.name.value('.','NVARCHAR(MAX)') As [Value]
FROM @XML.nodes('/*/@*') attribute(name);

SELECT
    CAST(attribute.name.query('local-name(.)') AS VARCHAR(MAX)) As [Name],
    attribute.name.value('.','NVARCHAR(MAX)') As [Value]
FROM @XML.nodes('/node()/@*') attribute(name);

SELECT
    CAST(attribute.name.query('local-name(.)') AS VARCHAR(MAX)) As [Name],
    attribute.name.value('.','NVARCHAR(MAX)') As [Value]
FROM @XML.nodes('/root/@*') attribute(name);

返回:

Name      Value
--------- --------
root_attr 0

我们有。一些XPath重言式围绕&#34; //&#34;保留字。