如何处理sql中xml标记之间的前导空格
Posted
技术标签:
【中文标题】如何处理sql中xml标记之间的前导空格【英文标题】:How to handle leading white space between xml tag in sql 【发布时间】:2019-12-22 10:14:12 【问题描述】:我的 SQL 表列具有如下 xml 数据
我正在尝试根据特定标签值 ( age ) 查找元素。但是,我的 xml 值具有前导空格。所以,它在条件上失败了。请指导我处理这个。
例子:
declare @age2 varchar(40)='23'
declare @ageNew2 varchar(40)='43'
declare @xmldata xml='<Root>
<Identification Name="John" Family="Brown"><Age>40</Age><name>xxx</name></Identification>
<Identification Name="Smith" Family="Johnson"><Age>35</Age><name>xxx</name></Identification>
<Identification Name="Jessy" Family="Albert"><Age>60</Age><name>xxx</name></Identification>
<Identification Name="Mike" Family="Brown"><Age>23</Age><name>xxx</name></Identification>
<Identification Name="Sarah" Family="Johnson"><Age>40</Age><name>xxx</name></Identification>
<Identification Name="Jessy" Family="Albert"><Age>40</Age><name>xxx</name></Identification>
<Identification Name="Mike" Family="Brown"><Age>23 </Age><name>xxx</name></Identification>
<Identification Name="Sarah" Family="Johnson"><Age>45</Age><name>xxx</name></Identification>
</Root>'
declare @dynamicData varchar(max)
set @dynamicData=' declare @xml varchar(max) ='''+Convert(varchar(max),@xmldata)+''' '
set @dynamicData +=' declare @xmld xml=convert(xml,@xml) '
set @dynamicData +=' declare @age varchar(55) ='''+@age2+''''
set @dynamicData +=' declare @ageNew varchar(55) ='''+@ageNew2+''''
DECLARE @nodeCount int
DECLARE @i int
SET @i = 0
SELECT @nodeCount = @xmldata.value('count(/Root/Identification/Age)','int')
WHILE (@i < @nodeCount)
BEGIN
set @dynamicData+=' set @xmld.modify(''replace value of (/Root/Identification[Age=sql:variable("@age")]/name/text())['+convert(varchar(10),@i)+'] with "'+@ageNew2+'"'') '
SET @i = @i + 1
END
set @dynamicData+=' select convert(xml,@xmld) '
exec(@dynamicData)
在这里,我正在尝试将 23 岁更新为 43 岁。所以,按照我的预期。它应该替换两个地方。但是,它单独替换第一个。因为,第二个有空间。 所以,请指导我。谢谢
【问题讨论】:
请edit您的问题包括样本数据和期望的结果。 看看***.com/questions/12488213/how-to-use-like-in-xpath,尤其是endswith的解决方法可能会有所帮助 @ZoharPeled 请检查。我已经更新了 【参考方案1】:您可以尝试将 Age/text() 转换为令牌以删除所有空格(如果这是您真正需要的)
替换 (/Root/Identification[xs:token(Age[1])=sql:variable("@age")]/name/text()) 的值
【讨论】:
好答案,我这边+1!智能使用数据类型转换来模拟 SQL Servernormalized-space()
函数中的缺失【参考方案2】:
如果搜索变量是整数,那么它可以工作。 因为它然后获得了隐式转换的好处。
所以首先将它转换为一个 INT 变量,然后使用它。
示例 sn-p:
DECLARE @xmldata XML = N'<Root>
<Identification Name="John" Family="Brown"><Age>40</Age><name>xxx</name></Identification>
<Identification Name="Smith" Family="Johnson"><Age>35</Age><name>xxx</name></Identification>
<Identification Name="Jessy" Family="Albert"><Age>60</Age><name>xxx</name></Identification>
<Identification Name="Mike" Family="Brown"><Age>23</Age><name>xxx</name></Identification>
<Identification Name="Sarah" Family="Johnson"><Age>40</Age><name>xxx</name></Identification>
<Identification Name="Jessy" Family="Albert"><Age>40</Age><name>xxx</name></Identification>
<Identification Name="Mike" Family="Brown"><Age>23 </Age><name>xxx</name></Identification>
<Identification Name="Sarah" Family="Johnson"><Age>45</Age><name>xxx</name></Identification>
</Root>';
DECLARE @age2 VARCHAR(40)='23';
DECLARE @ageNew2 VARCHAR(40)='43';
--
-- let us use an int to search
--
DECLARE @age2int INT = cast(@age2 as int);
--
-- how many to modify
--
DECLARE @cnt int = @xmldata.value('count(/Root/Identification/Age[.=sql:variable("@age2int")])','int');
--
-- loop over the elements to modify
--
WHILE @cnt > 0
BEGIN
SET @xmldata.modify('replace value of (/Root/Identification/Age[.=sql:variable("@age2int")]/text())[1] with sql:variable("@ageNew2")');
SET @cnt = @cnt - 1;
END;
对 rextester 的测试here
【讨论】:
id 是字母数字而非整数。它的 varchar @NatarajanVeerasekaran 你能在你的问题中添加一个例子吗?文字很好。 T-sql代码也不错。 好的,但我认为数据会有 id 的?但似乎你试图改变所有 23 岁的人。对吗? @NatarajanVeerasekaran 有点晚了,但更新了。我确实喜欢另一个答案的把戏。以上是关于如何处理sql中xml标记之间的前导空格的主要内容,如果未能解决你的问题,请参考以下文章