【问题标题】:Replace XML string using SQL Server Replace or CLR Regex?使用 SQL Server Replace 或 CLR Regex 替换 XML 字符串?
【发布时间】:2015-03-17 06:47:00
【问题描述】:

我有以下 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 Server 中执行,还是需要使用 CLR 函数才能使用正则表达式?

函数必须是通用的,因为列名会不同。

【问题讨论】:

  • 如果你有另一行怎么办?它将连接到第一行还是分开?会有多少个不同的节点(id、name、amount)?
  • @Darka 编辑了我的问题以回答您的问题。
  • Sql server vs clr ??这取决于实际情况。我们不能只看1个小样本数据。如果没有列和没有。的行数较少且不经常使用,那么我们可以使用以下查询。

标签: c# sql-server regex clr sql-server-2014


【解决方案1】:

您可以使用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^

Example at SQL Fiddle.

【讨论】:

  • select ','+ col1.value('local-name(.)', 'varchar(max)') + ' || ' + col1.value('(./new)[1]', 'varchar(max)') + ' ^ ' from @xml.nodes('/row/*') as tbl(col1) for xml path( '')
【解决方案2】:

这应该可以,如果 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));

最后替换“行”开始和结束标签...

希望这会有所帮助...

【讨论】:

  • 据说,“如果你只有一把锤子,那么一切看起来都像钉子。”解析 XML 有比regular expressions 更好的方法
  • 嗨,Andomar,您说的对处理 XML 的方法比正则表达式更好。我使用了正则表达式,因为 Ivan 或 Darka 对正则表达式没问题。无论如何,谢谢..
【解决方案3】:

试试这个,

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)

【讨论】:

  • OP 表示事先不知道 XML 节点的名称。所以除了“id”、“name”和“amount”之外,可能还有其他。
  • 是的,这是我当前查询的缺点。同时我在想。
  • 是的,甚至在他的问题标题中:)
猜你喜欢
  • 2011-07-11
  • 1970-01-01
  • 2016-06-23
  • 1970-01-01
  • 1970-01-01
  • 2014-04-19
  • 1970-01-01
  • 2019-04-30
  • 1970-01-01
相关资源
最近更新 更多