我尝试创建一个程序来搜索xml文件中<disp-formula id="deqnX-Y">
形式的节点,创建一个字典,其中的键就像rid="deqnX" ... rid="deqnY"
,(其中 X < / strong>增加+1直到达到 Y )并且它们各自的值对应类似于rid="deqnX-Y"
每个,然后我可以简单地进行搜索并使用字典替换以更改链接节点。即如果文件中有<disp-formula id="deqn5-7">, <disp-formula id="deqn9-11">, <disp-formula id="deqn3a-3c">, <disp-formula id="deqn4p-5b">
之类的节点,并且表格中有链接节点
<xref ref-type="disp-formula" rid="deqn5">
<xref ref-type="disp-formula" rid="deqn6">
<xref ref-type="disp-formula" rid="deqn10">
<xref ref-type="disp-formula" rid="deqn5c">
应改为
<xref ref-type="disp-formula" rid="deqn5-7">
<xref ref-type="disp-formula" rid="deqn5-7">
<xref ref-type="disp-formula" rid="deqn9-11">
<xref ref-type="disp-formula" rid="deqn4p-5b">
我现在使用以下代码
void Button1Click(object sender, EventArgs e)
{
string active_filename = "";
string DirectoriesName = textBox1.Text;
string[] path = Directory.GetDirectories(DirectoriesName, "xml", SearchOption.AllDirectories)
.SelectMany(x => Directory.GetFiles(x, "*.xml", SearchOption.AllDirectories)).ToArray();
Dictionary<string, string> dict = new Dictionary<string, string> ();
var re = new Regex(@"deqn(\w+)-(\w+)");
foreach (var file in path)
{
dict.Clear();
active_filename = file;
XDocument doc = XDocument.Load(file, LoadOptions.PreserveWhitespace);
IEnumerable<XAttribute> list_of_elements = doc.Descendants("disp-formula").Where(z => (z.Attribute("id") != null) && re.IsMatch(z.Attribute("id").Value)).Attributes("id");
foreach (XAttribute ele in list_of_elements)
{
int from = 0, to = 0;
string strform = re.Match(ele.Value).Groups[1].Value;
string strTo = re.Match(ele.Value).Groups[2].Value;
Boolean bfrom = int.TryParse(strform,out from);
Boolean bto = int.TryParse(strTo,out to);
if (bfrom && bto)
{
for (int i = from; i <= to; i++)
dict.Add("rid=\"deqn" + i + "\"", "rid=\"" + ele.Value + "\"");
}
else {
for (int i = base36toInt(strform); i <= base36toInt(strTo); i++)
{
int temp = 0;
if (!int.TryParse(IntTo36Base(i), out temp))
{
dict.Add("rid=\"deqn" + IntTo36Base(i) + "\"", "rid=\"" + ele.Value + "\"");
}
}
}
foreach (KeyValuePair<string, string> element in dict)
{
//do a search all replace all (search Key and replace by Value
string text = File.ReadAllText(file);
text = text.Replace(element.Key, element.Value);
File.WriteAllText(file, text);
}
}
}
MessageBox.Show("Done");
}
public static int base36toInt(string s)
{
char[] baseChars = "0123456789abcdefghijklmnopqrstuvwxyz".ToCharArray();
char[] target = s.ToCharArray();
double result = 0;
for (int i = 0; i < target.Length; i++)
{
result += Array.IndexOf(baseChars, target[i]) * Math.Pow(baseChars.Length, target.Length - i - 1);
}
return Convert.ToInt32(result);
}
public static string IntTo36Base(int value)
{
char[] baseChars = "0123456789abcdefghijklmnopqrstuvwxyz".ToCharArray();
string result = string.Empty;
int targetBase = baseChars.Length;
do
{
result = baseChars[value % targetBase] + result;
value = value / targetBase;
}
while (value > 0);
return result;
}
但是当文件中有<disp-formula id="deqn5-7c">
或<disp-formula id="deqn2a-4">
等节点时会出现问题。我得到的错误是 System.IO.IOException:无法对打开了用户映射部分的文件执行请求的操作。我如何摆脱这个错误。
此外,我希望程序忽略<disp-formula id="deqn5-7c">
和/或<disp-formula id="deqn2a-4">
之类的节点,这样做最有效的方法是什么?
答案 0 :(得分:1)
好吧,这可能是一个愚蠢的答案,但是......你想过改变你的正则表达式吗?我的意思是,现在,它将匹配“deqn”,然后是任何字母数字字符串,接着是“ - ”,然后是另一个字母数字流。所以即使像“deqnasdf-zxcv”这样的东西也适合。
我建议将其更改为:“deqn(\ d +) - (\ d +)” - 也就是说,将“任何字母数字”更改为“任何数字”。我的意思是,如果你想跳过像deqn1-2c这样的东西,这将阻止他们甚至出现在比赛中。另外,你越是缩小你的正则表达式,你未来计划的匹配就越容易出错。
答案 1 :(得分:1)
我明白了:
System.IO.IOException:无法对打开了用户映射部分的文件执行请求的操作。
似乎您想要更改它正在使用的文件,因此您无法更改它。因为你说有时它会发生,所以我猜你的循环正在引发错误。它可以快速打开和关闭文件,同时可以从循环中打开文件并在循环后写入文件。无论如何,当您通过Process Explorer等程序收到上述错误时,您可以找到正在使用该文件的应用。
测试一下:
而不是使用此代码:
foreach (KeyValuePair<string, string> element in dict)
{
//do a search all replace all (search Key and replace by Value
string text = File.ReadAllText(file);
text = text.Replace(element.Key, element.Value);
File.WriteAllText(file, text);
}
使用这个:
string text = File.ReadAllText(file);
foreach (KeyValuePair<string, string> element in dict)
{
//do a search all replace all (search Key and replace by Value
text = text.Replace(element.Key, element.Value);
}
File.WriteAllText(file, text);