尝试通过Xpath查询返回XML字段的值。
这是XML快照中的样子。
<?xml version="1.0" encoding="utf-16"?>
<ArrayOfCustomProperty xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<CustomProperty>
<DeveloperId>Test123</DeveloperId>
<Key>AgreedToTerms</Key>
<Value>True</Value>
</CustomProperty>
<CustomProperty>
<DeveloperId>Test456</DeveloperId>
<Key>ValidForLoyaltyPoints</Key>
<Value>False</Value>
</CustomProperty>
</ArrayOfCustomProperty>
(抱歉,XML格式不正确... StackOverflows RCE呈现它时出现问题。ArrayOfCustomProperty最后关闭,由于某种原因而没有显示)
此查询对我有用。...
SET @return = CAST(CAST(@xmlData AS xml).query('ArrayOfCustomProperty/CustomProperty/Key[text()=sql:variable("@key")]/../Value/text()') AS nvarchar(255))
它使我可以使用一个函数,其中的参数分别是@xmlData和@key以供需要搜索的内容使用。我需要有另一个函数(或可能会修改它),在这里我也可以搜索[DeveloperId]节点,因此第三个参数将作为@devId传递。我已经尝试了很多不同的东西,但是对我来说还没有任何作用。我想要一个查询,当使用相同的结构(如果可能)显示[DeveloperId]和[Key]时,可以获取[Value],该结构与当前Xpath查询的工作方式相同。
在此先感谢您的帮助。
答案 0 :(得分:1)
您可以将xml
数据转换为表格,然后处理该表格。像这样的东西。
declare @xml xml=N'<?xml version="1.0" encoding="utf-16"?>
<ArrayOfCustomProperty xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<CustomProperty>
<DeveloperId>Test123</DeveloperId>
<Key>AgreedToTerms</Key>
<Value>True</Value>
</CustomProperty>
<CustomProperty>
<DeveloperId>Test456</DeveloperId>
<Key>ValidForLoyaltyPoints</Key>
<Value>False</Value>
</CustomProperty>
</ArrayOfCustomProperty>',
@key varchar(50)
;with cte as (
select t.v.value('DeveloperId[1]','varchar(50)') DeveloperId,
t.v.value('Key[1]','varchar(50)') [Key],
t.v.value('Value[1]','varchar(50)') [Value]
from @xml.nodes('ArrayOfCustomProperty/CustomProperty') t(v)
)
select * from cte
where [Key] = @key
答案 1 :(得分:1)
您应该尝试尽可能少地从XML返回。
最好的办法是将引擎必须解析的数量减少到所需的最小值。
并且您应该避免使用../
向后导航。这是一个众所周知的性能杀手。
尝试一下:
DECLARE @tbl TABLE(YourXml XML);
INSERT INTO @tbl VALUES
(N'<?xml version="1.0" encoding="utf-16"?>
<ArrayOfCustomProperty xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<CustomProperty>
<DeveloperId>Test123</DeveloperId>
<Key>AgreedToTerms</Key>
<Value>True</Value>
</CustomProperty>
<CustomProperty>
<DeveloperId>Test456</DeveloperId>
<Key>ValidForLoyaltyPoints</Key>
<Value>False</Value>
</CustomProperty>
</ArrayOfCustomProperty>');
-您的键变量
DECLARE @key VARCHAR(100)='ValidForLoyaltyPoints' ;
-查询
SELECT cp.value('(DeveloperId/text())[1]','nvarchar(250)') AS DeveloperId
,cp.value('(Value/text())[1]','nvarchar(250)') AS Value
FROM @tbl t
CROSS APPLY t.YourXml.nodes('/ArrayOfCustomProperty/CustomProperty[(Key/text())[1]=sql:variable("@key")]') A(cp);
XPath/XQuery
中的.nodes()
将跳至<CustomProperty>
,并返回带有<Key>
的那个,其中键的文本类似于给定的过滤器。返回找到的<CustomProperty>
。使用.value()
,我们可以读取此给定属性下的元素。
看起来,好像您试图根据<Value>
和<DeveloperId>
来获取<Key>
作为标量值一样。您可以使用简单的谓词一次查询两者:
DECLARE @key VARCHAR(100)='ValidForLoyaltyPoints' ;
DECLARE @devId VARCHAR(100)='Test456';
--the Query
SELECT t.YourXml.value(N'(/ArrayOfCustomProperty
/CustomProperty[(DeveloperId/text())[1]=sql:variable("@devId")
and (Key/text())[1]=sql:variable("@key")]
/Value/text())[1]',N'nvarchar(100)')
FROM @tbl t;
您读为
答案 2 :(得分:0)
@Shnugo
这是您最后一次评论的意思吗?
DECLARE @tbl TABLE(YourXml XML);
INSERT INTO @tbl VALUES (@xmlData)
SELECT t.YourXml.value('(/ArrayOfCustomProperty/CustomProperty/Value/text())[1]','nvarchar(250)') AS Value
FROM @tbl t
WHERE t.YourXml.value('(/ArrayOfCustomProperty/CustomProperty/Key/text())[1]','nvarchar(250)') = @key
AND
t.YourXml.value('(/ArrayOfCustomProperty/CustomProperty/DeveloperId/text())[1]','nvarchar(250)') = @devId