可能会更简单一点:
SELECT x.n.value('.', 'nvarchar(20)') as 'Name'
FROM @result.nodes('/A
/B
/*[local-name() =sql:variable("@NodePath")]
/@*[local-name()=sql:variable("@NodeVariable")]') x(n)
简而言之:
- 深入
<B> 下方(或使用深度搜索和//,如果你可以确定,在任何其他地方都不会有<C>)
- 查找具有给定名称的任何元素
- 选择具有给定名称的属性(每个定义的每个元素的属性都是单例的)
- 在当前节点上使用
value()返回内容。
可能会造成干扰:<C> 多次出现在 <B> 下方
更新 XPath 和 local-name() 的一些补充
试试这个:
declare @result xml =
N'<A>
<B>
<C name="Name01"/>
</B>
<TheSecondInA />
<B>
<C name = "Name02"/>
</B>
<OneMore someAttr="x" oneMoreAttr="y" theLastAttr="z" >SomeText</OneMore>
</A>';
SELECT @result.value('local-name((//TheSecondInA)[1])','varchar(100)')
,@result.value('local-name((/A/*[2])[1])','varchar(100)')
,@result.value('local-name(/A[1]/*[2])','varchar(100)')
,@result.value('local-name((//*[@someAttr]/@*[2])[1])','varchar(100)')
,@result.value('local-name((/A/OneMore/@*[3])[1])','varchar(100)')
,@result.value('local-name((/A/OneMore/@*[last()])[1])','varchar(100)')
,@result.value('local-name((/A/OneMore/text())[1])','varchar(100)')
,@result.value('local-name((/DoesNotExist)[1])','varchar(100)')
如您所见,函数local-name() 必须获得一个单例XPath。
-
深度搜索会深入到命名节点的第一次出现
-
<A> 下面的第二个元素返回相同的值
- 如果路径本身保证返回单例,我们不需要这个
(SomeXpath)[1]。
- 在这里,我们深入到第一个元素,其中有一个名为
someAttr 的属性,并根据其位置选择第二个属性。
- 类似地,我们可以选择给定路径上的第三个属性
- 要获取最后一个属性(或元素),我们可以使用
last()
- 如果当前节点是
text() 节点,或者该元素不存在,我们会返回一个空字符串。
提示:使用类似的 XPath 表达式,您可以使用 .value() 检索本地内容,.exist() 测试是否存在(或不存在)并修改给定位置...