XML文件中的C#正则表达式
Posted
技术标签:
【中文标题】XML文件中的C#正则表达式【英文标题】:C# Regex in XML file 【发布时间】:2020-08-16 20:57:58 【问题描述】:我有一个 XML 文件,其中多次包含以下字符串:
<Name Area="" Title="@(String) - @(I am) - @(looking) - @(for)" ...</Name>
我想做的是用正则表达式搜索这些字符串,切掉 @() 并将其余部分保存在新的文本文件中。 我已经设法找到与该字符串匹配的模式,计算该模式与该字符串匹配的频率,但我未能挑选和操作它们。
我在 Windows 窗体应用程序中完成所有这些工作。
编辑:
莫顿·博克:
到目前为止,我唯一能做的就是让用户选择要处理的文件以及保存新文件的位置。它正在这样做。我对使用正则表达式的想法失败了。
using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Diagnostics;
using System.Text.RegularExpressions;
namespace Movitool
public partial class Form1 : Form
public Form1()
InitializeComponent();
public static class Globals
public static string AlrFile = string.Empty;
public static string AlrFileNeu = string.Empty;
private void btnPfadAuswahl_Click(object sender, EventArgs e)
using (OpenFileDialog fileDialog1 = new OpenFileDialog())
fileDialog1.Filter = "movalr files (*.movalr)|*.movalr";
fileDialog1.RestoreDirectory = true;
fileDialog1.InitialDirectory = @"Dokumente\";
if (fileDialog1.ShowDialog() == DialogResult.OK)
Globals.AlrFile = fileDialog1.FileName;
txtPfad.Text = Globals.AlrFile;
private void btnStartAlr_Click(object sender, EventArgs e)
string pattern = @"@(.*?)";
Regex rgx = new Regex(pattern);
using (SaveFileDialog fileDialog2 = new SaveFileDialog())
fileDialog2.InitialDirectory = @"Dokumente";
fileDialog2.Title = "Save File";
fileDialog2.Filter = "txt files (*.txt)|*.txt";
if(fileDialog2.ShowDialog() == DialogResult.OK)
Globals.AlrFileNeu = fileDialog2.FileName;
foreach(string Line in File.ReadLines(Globals.AlrFile))
File.AppendAllText(Globals.AlrFileNeu, Line + Environment.NewLine);
lblStatus.Text = "Fertig!";
【问题讨论】:
您是否使用 RegEx 搜索 XML? IMO,最好将 XML 转储到XDocument
,将字符串(在您的 sn-p 中它们是 Title 属性的值)提取到集合中,然后对字符串中的字符串执行 RegEx收藏。
您需要展示您的尝试,提供足够的代码来复制您的问题等。请查看“如何提问”部分。
【参考方案1】:
尝试以下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
namespace ConsoleApplication1
class Program
const string FILENAME = @"c:\temp\test.txt";
static void Main(string[] args)
string input = File.ReadAllText(FILENAME);
string pattern = @"(?'start'@\()(?'middle'[^\)]+)(?'end'\))";
string output = Regex.Replace(input, pattern, "$middle");
这是使用您的数据的输出
<?xml version="1.0" encoding="ISO-8859-1" ?>
<Alarms>
<AlarmList>
<Alarm>
<Name Device="" Variable="" Area="1" ThresholdExclusive="0" Enabled="1" OnQualityGood="1" VariableDuration="0" EnableVariable="" EnableDispMsg="" Hysteresis="0" EventsCache="1024"></Name>
<ThresholdList>
<Threshold>
<Name Area="" Title="My - Searched - String" Help="" DurationFormat="" ReadAccessLevel="4294901760" WriteAccessLevel="4294901760">On</Name>
<Execution Condition="2" Threshold="1" ThresholdVar="" ThresholdLow="0" ThresholdVarLow="" VariableStatus="" Severity="10" SeverityVar="" SecDelay="0" RunCommandAtServer="0"/>
<Commands/>
<CommandsOn/>
<CommandsAck/>
<CommandsReset/>
<CommandsOff/>
<Style BackColor="4294967295" TextColor="65535" BlinkBackColor="4294967295" BlinkTextColor="4294967295" Print="1" Log="1" BlinkOnNewAlarm="0" VarTimeStamp="0" SupportAck="0" SupportReset="0" SupportResetConditionOn="0" BmpFile="" SndFile="" BeepEnabled="0" SpeechEnabled="0" RepeatSpeechEverySec="0" EnableSpeechVariable="" PlaysoundContinuosly="0" CommentOnAck="0"/>
<Recipient Attachment="" DispatchingText=""/>
<SendEmail SendON="0" SendACK="0" SendRESET="0" SendOFF="0"/>
<SendVoice SendON="0" SendACK="0" SendRESET="0" SendOFF="0"/>
<SendSMS SendON="0" SendACK="0" SendRESET="0" SendOFF="0"/>
<SendFax SendON="0" SendACK="0" SendRESET="0" SendOFF="0"/>
<SendAdminAlert SendON="0" SendACK="0" SendRESET="0" SendOFF="0"/>
<SendMessenger SendON="0" SendACK="0" SendRESET="0" SendOFF="0"/>
<ScriptCode StartSel="0" SelLength="0" OutStatusBar="1" OutLog="1" OutPrinter="1">
</ScriptCode>
</Threshold>
</ThresholdList>
</Alarm>
</AlarmList>
</Alarms>
这里只是使用 xml linq 更改的标题
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
class Program
const string FILENAME = @"c:\temp\test.txt";
static void Main(string[] args)
XDocument doc = XDocument.Load(FILENAME);
string pattern = @"(?'start'@\()(?'middle'[^\)]+)(?'end'\))";
foreach(XElement xTitle in doc.Descendants("Name").Where(x => x.Attribute("Title") != null))
string title = (string)xTitle.Attribute("Title");
Console.WriteLine("Title : " + Regex.Replace(title, pattern, "$middle"));
Console.ReadLine();
【讨论】:
谢谢你的回答,但我的问题是我不知道字符串的样子,它们总是不同的。 你试过代码了吗?我只是删除了“@(”和关闭的“)”。我刚刚用你的字符串测试过。输入可以是任何东西。 是的,我必须遍历文件,其中我搜索的字符串之前和之后是其他属性。 显然您没有尝试该代码,如果您尝试过,您会看到它有效。我认为您需要阅读 RegEx 上的文档才能真正理解我所做的事情:docs.microsoft.com/en-us/dotnet/standard/base-types/… 我用你的 xml 文件更新了我的代码。该代码有效。看看我的输出。【参考方案2】:回答jdweng的最后一条评论:
是的,我已经尝试过您的代码。我也尝试将它与 Tim 的答案混合在一起,他说要使用 XDocument。 我现在尝试的是:
XmlReader xr = new XmlTextReader(Globals.AlrFile);
lblMatches.Text = "";
while (xr.Read())
if(xr.NodeType == XmlNodeType.Element)
if(xr.AttributeCount > 0)
while(xr.MoveToNextAttribute())
string input = Convert.ToString(xr.Value);
string pattern = @"(?'start'@\()(?'middle'[^\)]+)(?'end'\))";
string output = Regex.Replace(input, pattern, "$middle");
File.AppendAllText(Globals.AlrFileNeu, output + Environment.NewLine);
xr.Close();
但我的 xml 输入是这样的:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<Alarms>
<AlarmList>
<Alarm>
<Name Device="" Variable="" Area="1" ThresholdExclusive="0" Enabled="1" OnQualityGood="1" VariableDuration="0" EnableVariable="" EnableDispMsg="" Hysteresis="0" EventsCache="1024"></Name>
<ThresholdList>
<Threshold>
<Name Area="" Title="@(My) - @(Searched) - @(String)" Help="" DurationFormat="" ReadAccessLevel="4294901760" WriteAccessLevel="4294901760">On</Name>
<Execution Condition="2" Threshold="1" ThresholdVar="" ThresholdLow="0" ThresholdVarLow="" VariableStatus="" Severity="10" SeverityVar="" SecDelay="0" RunCommandAtServer="0"/>
<Commands/>
<CommandsOn/>
<CommandsAck/>
<CommandsReset/>
<CommandsOff/>
<Style BackColor="4294967295" TextColor="65535" BlinkBackColor="4294967295" BlinkTextColor="4294967295" Print="1" Log="1" BlinkOnNewAlarm="0" VarTimeStamp="0" SupportAck="0" SupportReset="0" SupportResetConditionOn="0" BmpFile="" SndFile="" BeepEnabled="0" SpeechEnabled="0" RepeatSpeechEverySec="0" EnableSpeechVariable="" PlaysoundContinuosly="0" CommentOnAck="0"/>
<Recipient Attachment="" DispatchingText=""/>
<SendEmail SendON="0" SendACK="0" SendRESET="0" SendOFF="0"/>
<SendVoice SendON="0" SendACK="0" SendRESET="0" SendOFF="0"/>
<SendSMS SendON="0" SendACK="0" SendRESET="0" SendOFF="0"/>
<SendFax SendON="0" SendACK="0" SendRESET="0" SendOFF="0"/>
<SendAdminAlert SendON="0" SendACK="0" SendRESET="0" SendOFF="0"/>
<SendMessenger SendON="0" SendACK="0" SendRESET="0" SendOFF="0"/>
<ScriptCode StartSel="0" SelLength="0" OutStatusBar="1" OutLog="1" OutPrinter="1">
</ScriptCode>
</Threshold>
</ThresholdList>
</Alarm>
</AlarmList>
</Alarms>
我在新文本文件中得到的输出是:
1
0
1
1
0
0
1024
My - Searched - String
4294901760
4294901760
2
1
0
10
0
0
4294967295
65535
4294967295
4294967295
1
1
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
1
1
1
我的问题是我只需要 Title 属性之间的文本,并且我有多个警报元素要通过。
【讨论】:
您不需要使用 XDocument。您将结果附加到原始结果中并弄得一团糟。看看我上面发布的结果。以上是关于XML文件中的C#正则表达式的主要内容,如果未能解决你的问题,请参考以下文章
如何使用正则表达式匹配从 xml 文件中搜索和替换包含占位符标记的文本。 VB.net 或 C#
匹配 XML 字符串的正则表达式在 C# 中具有开始和结束标记