我有如下的XML:
<BODY>
<RECORD>
<PA0002_NATIO>CH</PA0002_NATIO>
<PA0001_CITY>Lugano</PA0001_CITY>
<PA0005_VALUE>1000</PA0005_VALUE>
</RECORD>
<RECORD>
<PA0002_NATIO>DE</PA0002_NATIO>
<PA0001_CITY>Berlin</PA0001_CITY>
<PA0005_VALUE>2000</PA0005_VALUE>
</RECORD>
<RECORD>
<PA0002_NATIO>IT</PA0002_NATIO>
<PA0001_CITY>Roma</PA0001_CITY>
<PA0005_VALUE>3000</PA0005_VALUE>
</RECORD>
</BODY>
我想在所有<PA0002_NATIO>
个节点中更改标记<RECORD>
的值,为了做到这一点,我计算了<RECORD>
个节点的数量,我做了一个循环这个,新值取自表格。
if @countNodes > 0
begin
set @indexCount = 1
while @indexCount <= @countNodes
begin
-- get the value from the node
set @nodevalue = (@xml.value('(//RECORD[sql:variable("@indexCount")]/PA0002_NATIO/text())[1]', 'nvarchar(50)'))
-- find in the table the value to be replaced
set @repvalue = (select [Target Code] from [Ronal].[dbo].['Value Mapping$']
where [List Name]='Nationality' and [SAP Code]=@nodevalue)
-- replace the value in the node
set @xml.modify('
replace value of
(//RECORD[sql:variable("@indexCount")]/PA0002_NATIO/text())[1]
with
sql:variable("@repvalue")
');
SET @Indexcount= @Indexcount + 1;
end
end
END
现在的想法是使用xpath中的变量进行泛型替换 而不是使用
set @nodevalue = (@xml.value('(//RECORD[sql:variable("@indexCount")]/PA0002_NATIO/text())[1]', 'nvarchar(50)'))
我会用
set @nodevalue = (@xml.value('(//RECORD[sql:variable("@indexCount")]/[sql:variable("@tag")]/text())[1]', 'nvarchar(50)'))
当然我会使用相同的语法来替换
-- replace the value in the node
set @xml.modify('
replace value of
(//RECORD[sql:variable("@indexCount")]/[sql:variable("@tag")]/text())[1]
with
sql:variable("@repvalue")
');
@tag
变量包含<PA0002_NATIO>
但<PA0001_CITY>
等等,从另一个存储标记名称的表中获取数据。
我该怎么做?
答案 0 :(得分:1)
你需要一个棘手的.modify
循环:
--declare table with names and ids like you posted in comment
DECLARE @test TABLE (
Name nvarchar(2),
id nvarchar(2)
)
INSERT INTO @test VALUES
('CH', '00'),
('DE', '01'),
('IT', '02')
DECLARE @xml XML = '
<BODY>
<RECORD>
<PA0002_NATIO>CH</PA0002_NATIO>
<PA0001_CITY>Lugano</PA0001_CITY>
<PA0005_VALUE>1000</PA0005_VALUE>
</RECORD>
<RECORD>
<PA0002_NATIO>DE</PA0002_NATIO>
<PA0001_CITY>Berlin</PA0001_CITY>
<PA0005_VALUE>2000</PA0005_VALUE>
</RECORD>
<RECORD>
<PA0002_NATIO>IT</PA0002_NATIO>
<PA0001_CITY>Roma</PA0001_CITY>
<PA0005_VALUE>3000</PA0005_VALUE>
</RECORD>
</BODY>';
DECLARE @Counter int = 1,
@newValue nvarchar(max),
@nodename nvarchar(max) ='PA0002_NATIO'
WHILE @Counter <= @xml.value('fn:count(//*//*//*[local-name()=sql:variable("@nodename")])','int')
BEGIN
SELECT @newValue = id
FROM @test
WHERE Name = CAST(@xml.query('((/*/*/*[local-name()=sql:variable("@nodename")])[position()=sql:variable("@Counter")]/text())[1]') as nvarchar(2))
SET @xml.modify('replace value of ((/*/*/*[local-name()=sql:variable("@nodename")])[position()=sql:variable("@Counter")]/text())[1] with sql:variable("@newValue")')
SET @Counter = @Counter + 1;
END
SELECT @xml;
输出:
<BODY>
<RECORD>
<PA0002_NATIO>00</PA0002_NATIO>
<PA0001_CITY>Lugano</PA0001_CITY>
<PA0005_VALUE>1000</PA0005_VALUE>
</RECORD>
<RECORD>
<PA0002_NATIO>01</PA0002_NATIO>
<PA0001_CITY>Berlin</PA0001_CITY>
<PA0005_VALUE>2000</PA0005_VALUE>
</RECORD>
<RECORD>
<PA0002_NATIO>02</PA0002_NATIO>
<PA0001_CITY>Roma</PA0001_CITY>
<PA0005_VALUE>3000</PA0005_VALUE>
</RECORD>
</BODY>