【发布时间】:2016-08-26 11:12:13
【问题描述】:
在将 XML 路径通过变量传递给 nodes() 方法时,我需要帮助。我查看了几个不同的帖子,发现可以使用local-name 和sql:variable 传递一个节点。下面的示例按预期工作:
DECLARE @XML_Path VARCHAR(MAX)
, @XML_In XML
SET @XML_Path = 'GetData'
SET @XML_In =
'
<GetData>
<test>234</test>
</GetData>
'
--THIS WORKS
SELECT Item_Idx = Nodes.value('(test)[1]' ,'INT')
FROM @XML_In.nodes('/*[local-name()=sql:variable("@XML_Path")]') Results(Nodes)
但是,当我尝试传递路径而不是单个节点时,它不起作用:
SET @XML_Path = 'GetData/Hello'
SET @XML_In =
'
<GetData>
<Hello>
<test>234</test>
</Hello>
</GetData>
'
--THIS DOES NOT WORK
SELECT Item_Idx = Nodes.value('(test)[1]' ,'INT')
FROM @XML_In.nodes('/*[local-name()=sql:variable("@XML_Path")]') Results(Nodes)
我需要能够在路径的另一部分之前传递一个始终不变的路径。因此,在我的示例中,“测试”部分始终相同,但其上方的路径会有所不同。
我怀疑local-name 不是这样做的方法。但是有没有其他方法可以做到这一点?
任何帮助将不胜感激。
我曾考虑过使用动态 SQL,但此代码将用于返回结果表的 UDF 中。
编辑:
我相信我不清楚自己要做什么。我需要能够将不同的 XML 路径传递到使用它们来分解 XML 的函数中。
示例 1
DECLARE @XML_In XML
SELECT @XML_In =
'
<RootNode1>
<ExtraNode1>
<Items>
<ExampleItem>
<SomeNode>100</SomeNode>
<Attributes>
<ID>1</ID>
<Name>a</Name>
<Value>123a</Value>
</Attributes>
</ExampleItem>
<ExampleItem>
<SomeNode>200</SomeNode>
<Attributes>
<ID>2</ID>
<Name>b</Name>
<Value>234</Value>
</Attributes>
</ExampleItem>
<ExampleItem>
<SomeNode>300</SomeNode>
<Attributes>
<ID>3</ID>
<Name>c</Name>
<Value>345</Value>
</Attributes>
</ExampleItem>
</Items>
</ExtraNode1>
</RootNode1>
'
SELECT SomeNode = Nodes.value('(../SomeNode)[1]' ,'INT')
, ID = Nodes.value('(ID)[1]' ,'INT')
, Name = Nodes.value('(Name)[1]' ,'VARCHAR(100)')
, Value = Nodes.value('(Value)[1]' ,'NVARCHAR(MAX)')
FROM @XML_In.nodes('/RootNode1/ExtraNode1/Items/ExampleItem/Attributes') Results(Nodes)
示例 2
DECLARE @XML_In XML
SELECT @XML_In =
'
<Example2Root>
<Entries>
<Entry>
<SomeNode>100</SomeNode>
<Fields>
<ID>1</ID>
<Name>a</Name>
<Value>123a</Value>
</Fields>
</Entry>
<Entry>
<SomeNode>200</SomeNode>
<Fields>
<ID>2</ID>
<Name>b</Name>
<Value>234</Value>
</Fields>
</Entry>
<Entry>
<SomeNode>300</SomeNode>
<Fields>
<ID>3</ID>
<Name>c</Name>
<Value>345</Value>
</Fields>
</Entry>
</Entries>
</Example2Root>
'
SELECT SomeNode = Nodes.value('(../SomeNode)[1]' ,'INT')
, ID = Nodes.value('(ID)[1]' ,'INT')
, Name = Nodes.value('(Name)[1]' ,'VARCHAR(100)')
, Value = Nodes.value('(Value)[1]' ,'NVARCHAR(MAX)')
FROM @XML_In.nodes('/Example2Root/Entries/Entry/Fields') Results(Nodes)
我希望能够将路径传递给函数,以便它可以执行此操作并将其作为表格返回:
SELECT SomeNode = Nodes.value('(../SomeNode)[1]' ,'INT')
, ID = Nodes.value('(ID)[1]' ,'INT')
, Name = Nodes.value('(Name)[1]' ,'VARCHAR(100)')
, Value = Nodes.value('(Value)[1]' ,'NVARCHAR(MAX)')
FROM @XML_In.nodes('SOME_PATH') Results(Nodes)
但我不知道如何使用路径参数。大多数时候路径会有所不同。
【问题讨论】:
-
我怀疑——除非通过编写动态 SQL——这是不可能的。
-
我也是这么想的。我可以在存储过程中使用动态 SQL 来执行此操作,然后使用 INSERT EXEC,但这似乎不是一个很好的解决方案。
-
不,它不漂亮。但是限制很明确,不能通过变量传递路径。
-
@Tomalak,将变量作为 XPath 传递是不可能的,但我非常感谢通配符在此类问题中的能力:-)
标签: sql xml tsql xml-parsing