简体   繁体   English

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

[英]Need to get attribute name-value pairs for root element only, in T-SQL query

I've created a table-valued function which returns a list of attribute name-value pairs, when fed an XML fragment, based on Ben Davis's excellent response here . 我已经创建了一个表值函数,它返回一个属性名称 - 值对的列表,当提供一个XML片段时,基于Ben Davis 在这里的出色响应。 It works, but returns a list of all the attribute name-value pairs in the entire fragment, when I'd like to restrict it to just those on the root element. 它工作,但返回整个片段中所有属性名称 - 值对的列表,当我想将它限制在根元素上的那些时。 How can I do this? 我怎样才能做到这一点? Thank you, from an XQuery newbie. 谢谢你,来自一个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: As it turns out after some experimentation, the selector 'node()/@*' works. ETA:经过一些实验证明,选择器'node()/ @ *'可以工作。 Thanks to those who helped. 感谢那些帮助过的人。

I am using this in a simple data-migration application or data pump front-ending Sitecore. 我在一个简单的数据迁移应用程序或数据泵前端Sitecore中使用它。 I've written a utility that can take POCO objects in .NET and get them into Sitecore, but now am constructed a migration and logging database. 我编写了一个可以在.NET中使用POCO对象并将它们导入Sitecore的实用程序,但现在构建了一个迁移和日志记录数据库。 Source objects are stored in one place as XML. 源对象作为XML存储在一个位置。 Thank you again. 再次感谢你。

This question has been answered in comments already so this is just a compilation with a bit of explanation. 这个问题已经在评论中得到了回答,所以这只是一个有点解释的汇编。

For the experiments we will use this XML: 对于实验,我们将使用此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>';

And we need to extract the list of the root element attributes: root_attr="0" . 我们需要提取根元素属性的列表: root_attr="0"

For the XPath reference we refer to MSDN XPath Syntax guide 有关XPath参考,请参阅MSDN XPath语法指南

So, "/" stands for "child" or "root node" if appears at the start of the pattern, "@" stands for "attribute", "*" stands for "any" and "." 因此,“/”代表“child”或“root node”如果出现在模式的开头,“@”代表“attribute”,“*”代表“any”和“。”。 stands for "current context". 代表“当前背景”。 Surely this should give us all the root attributes: 当然这应该给我们所有的根属性:

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

Instead it gives an error: Top-level attribute nodes are not supported . 相反,它会给出错误: 不支持顶级属性节点 There are two types of nodes in XML: < element >Element Value</element> and <element attribute ="Attribute Value" />. XML中有两种类型的节点 :< element >元素值</ element>和<element attribute =“Attribute Value”/>。 So, /@* XPath is interpreted as any attribute for the root of XML, not of the root element. 所以, /@*的XPath被解释 XML的根的任何属性,而不是根元素 In fact that can be illustrated with: 事实上可以说明:

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

Returning: 返回:

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

Which is an anonymous node representing the entire XML document. 这是表示整个XML文档的匿名节点。 '.' XPath would give the same result. XPath会给出相同的结果。

Ok, so we need to specify any element at the root of the XML document. 好的,我们需要在XML文档的根目录中指定任何元素 The syntax for that should have been "//" (child of anonymous root node = root element) should this expression not stand for "Recursive descent" (all children). 如果此表达式不代表“递归下降”(所有子项),则该语法应为“//”(匿名根节点的子节点=根元素)。 Indeed 确实

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

Returns full list of attributes of all elements: 返回所有元素的完整属性列表:

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

Ok, now we need a way to say in XPath "root" "element" instead of "rootelement" which is apparently a reserved word. 好的,现在我们需要一种方式在XPath中说“root”“element”而不是“rootelement”,这显然是一个保留字。 One way is to squeeze in "any", the other - to specify that it should be "node()" unless of cause we know the actual name of the root element. 一种方法是挤入“any”,另一种方法 - 指定它应该是“node()”,除非我们知道根元素的实际名称。

For the given XML those three are equal: 对于给定的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);

Returning: 返回:

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

There we are. 我们在那里。 A bit of XPath tautology to work around the "//" reserved word. 一些XPath重言式解决“//”保留字。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM