使用 SQL 服务器替换或 CLR 正则表达式替换 XML 字符串?
Replace XML string using SQL Server Replace or CLR Regex?
我有以下 XML 字符串:
<row>
<id>
<old></old>
<new>2151</new>
</id>
<name>
<old></old>
<new>test</new>
</name>
<amount>
<old></old>
<new>62</new>
</amount>
</row>
我需要解析并替换字符串,以便最终结果的格式为:
columnname|oldvalue|newvalue^
因此上面的例子看起来像这样:
id||2151^name||test^amount||62^
XML 字符串将始终包含一个 row
节点。其中的节点(即 id、名称、数量等)会有所不同,范围可以从几个节点到超过 100 个节点。然而,结构将始终相同。
是否可以直接在 SQL 服务器中执行此操作,或者我是否需要使用 CLR 函数才能使用正则表达式?
函数必须是通用的,因为列名会不同。
如果 XML 的模式完全相同且不会改变,就应该这样做。
string checkStr1 = @"<row>
<id>
<old></old>
<new>2151</new>
</id>
<name>
<old></old>
<new>test</new>
</name>
<amount>
<old></old>
<new>62</new>
</amount>
</row>";
Regex r1 = new Regex(@"\<([a-z]+)\>(?:\t|\r|\n|\s)*\<old\>(.*?)\<\/old\>(?:\t|\r|\n|\s)*\<new\>(.*?)\<\/new\>(?:\t|\r|\n|\s)*</[a-z]+?>");
MessageBox.Show(r1.Replace(checkStr1, m => "^" + m.Groups[1].Value + "|" + m.Groups[2].Value + "|" + m.Groups[3].Value));
最后替换 "row" 开始和结束标签...
希望这对您有所帮助...
您可以使用 local-name()
检索节点名称:
select col1.value('local-name(.)', 'varchar(max)') + '|' +
col1.value('(./old)[1]', 'varchar(max)') + '|' +
col1.value('(./new)[1]', 'varchar(max)') + '^'
from @x.nodes('/row/*') as tbl(col1)
-->
id||2151^
name||test^
amount||62^
试试这个,
Declare @xml xml='<row>
<id>
<old></old>
<new>2151</new>
</id>
<name>
<old></old>
<new>test</new>
</name>
<amount>
<old></old>
<new>62</new>
</amount>
</row>'
select 'id||'+ xmlData.Col.value('(./id)[1]', 'varchar(MAX)')+'^' +
'name||'+ xmlData.Col.value('(./name)[1]', 'varchar(MAX)')+'^' +
'amount||'+ xmlData.Col.value('(./amount)[1]', 'varchar(MAX)')+'^'
from @xml.nodes('//row') xmlData(Col)
我有以下 XML 字符串:
<row>
<id>
<old></old>
<new>2151</new>
</id>
<name>
<old></old>
<new>test</new>
</name>
<amount>
<old></old>
<new>62</new>
</amount>
</row>
我需要解析并替换字符串,以便最终结果的格式为:
columnname|oldvalue|newvalue^
因此上面的例子看起来像这样:
id||2151^name||test^amount||62^
XML 字符串将始终包含一个 row
节点。其中的节点(即 id、名称、数量等)会有所不同,范围可以从几个节点到超过 100 个节点。然而,结构将始终相同。
是否可以直接在 SQL 服务器中执行此操作,或者我是否需要使用 CLR 函数才能使用正则表达式?
函数必须是通用的,因为列名会不同。
如果 XML 的模式完全相同且不会改变,就应该这样做。
string checkStr1 = @"<row>
<id>
<old></old>
<new>2151</new>
</id>
<name>
<old></old>
<new>test</new>
</name>
<amount>
<old></old>
<new>62</new>
</amount>
</row>";
Regex r1 = new Regex(@"\<([a-z]+)\>(?:\t|\r|\n|\s)*\<old\>(.*?)\<\/old\>(?:\t|\r|\n|\s)*\<new\>(.*?)\<\/new\>(?:\t|\r|\n|\s)*</[a-z]+?>");
MessageBox.Show(r1.Replace(checkStr1, m => "^" + m.Groups[1].Value + "|" + m.Groups[2].Value + "|" + m.Groups[3].Value));
最后替换 "row" 开始和结束标签...
希望这对您有所帮助...
您可以使用 local-name()
检索节点名称:
select col1.value('local-name(.)', 'varchar(max)') + '|' +
col1.value('(./old)[1]', 'varchar(max)') + '|' +
col1.value('(./new)[1]', 'varchar(max)') + '^'
from @x.nodes('/row/*') as tbl(col1)
-->
id||2151^
name||test^
amount||62^
试试这个,
Declare @xml xml='<row>
<id>
<old></old>
<new>2151</new>
</id>
<name>
<old></old>
<new>test</new>
</name>
<amount>
<old></old>
<new>62</new>
</amount>
</row>'
select 'id||'+ xmlData.Col.value('(./id)[1]', 'varchar(MAX)')+'^' +
'name||'+ xmlData.Col.value('(./name)[1]', 'varchar(MAX)')+'^' +
'amount||'+ xmlData.Col.value('(./amount)[1]', 'varchar(MAX)')+'^'
from @xml.nodes('//row') xmlData(Col)