You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

XML节点属性替换程序IO异常解决及混合格式节点过滤问询

解决XML中混合格式disp-formula节点的过滤与IOException问题

第一步:精准识别并过滤混合格式节点

首先要明确我们需要处理的节点规则:仅保留disp-formula节点中id为deqnX-Y格式,且X和Y格式一致的节点(要么都是纯数字,要么都是包含数字+字母的36进制字符串),像deqn5-7c(X纯数字、Y混合)或deqn2a-4(X混合、Y纯数字)这类格式不一致的节点直接跳过。

实现过滤的核心代码

先写两个辅助判断方法,再结合正则匹配完成过滤:

// 判断字符串是否为纯数字
private static bool IsPureNumber(string s)
{
    return long.TryParse(s, out _);
}

// 匹配deqnX-Y格式的正则(忽略大小写)
private static readonly Regex ValidRangePattern = new Regex(@"^deqn([0-9a-z]+)-([0-9a-z]+)$", RegexOptions.IgnoreCase);

// 遍历disp-formula节点时的过滤逻辑
foreach (XmlNode formulaNode in xmlDoc.SelectNodes("//disp-formula[@id]"))
{
    string id = formulaNode.Attributes["id"].Value;
    var match = ValidRangePattern.Match(id);
    if (!match.Success) continue;

    string x = match.Groups[1].Value;
    string y = match.Groups[2].Value;

    // 判断X和Y格式是否一致:要么都是纯数字,要么都不是纯数字
    bool xIsPureNum = IsPureNumber(x);
    bool yIsPureNum = IsPureNumber(y);
    if ((xIsPureNum && !yIsPureNum) || (!xIsPureNum && yIsPureNum))
    {
        continue; // 跳过混合格式节点
    }

    // 后续的映射字典创建、节点替换逻辑...
}

第二步:解决System.IO.IOException异常

这个异常大概率是文件读写冲突导致的(比如程序同时读写同一个文件,或文件被其他进程占用),可以通过以下两种方式解决:

方式1:内存加载后一次性写入

先把整个XML文件读入内存的XmlDocument对象,处理完成后再一次性写入文件,避免长时间占用文件:

string filePath = "your-target.xml";
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(filePath);

// 执行所有节点处理逻辑(包括过滤混合格式)...

// 处理完成后覆盖原文件
xmlDoc.Save(filePath);

方式2:使用临时文件中转

如果担心覆盖原文件出错,或者文件被占用,可以先写入临时文件,处理完成后替换原文件:

string tempPath = Path.GetTempFileName();
xmlDoc.Save(tempPath);

// 替换原文件
File.Delete(filePath);
File.Move(tempPath, filePath);

第三步:优化大文件处理效率

如果你的XML文件体积较大,建议使用流式处理+哈希字典提升效率:

  • 用XmlReader流式读取节点,避免加载整个文件到内存;
  • 用Dictionary<string, string>存储rid映射,保证O(1)的查找速度。

流式处理示例代码

string filePath = "your-target.xml";
string tempPath = Path.GetTempFileName();
Dictionary<string, string> ridMap = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

// 第一遍遍历:收集符合条件的映射关系
using (XmlReader reader = XmlReader.Create(filePath))
{
    while (reader.Read())
    {
        if (reader.NodeType == XmlNodeType.Element && reader.Name == "disp-formula")
        {
            string id = reader.GetAttribute("id");
            if (id == null) continue;
            var match = ValidRangePattern.Match(id);
            if (!match.Success) continue;

            string x = match.Groups[1].Value;
            string y = match.Groups[2].Value;

            // 过滤混合格式
            bool xIsPureNum = IsPureNumber(x);
            bool yIsPureNum = IsPureNumber(y);
            if ((xIsPureNum && !yIsPureNum) || (!xIsPureNum && yIsPureNum))
                continue;

            // 转换36进制范围,生成所有映射键
            long start = Convert.ToInt64(x, 36);
            long end = Convert.ToInt64(y, 36);
            for (long i = start; i <= end; i++)
            {
                string rid = $"deqn{Convert.ToString(i, 36)}";
                if (!ridMap.ContainsKey(rid))
                    ridMap.Add(rid, id);
            }
        }
    }
}

// 第二遍遍历:替换xref节点的rid属性
using (XmlReader reader = XmlReader.Create(filePath))
using (XmlWriter writer = XmlWriter.Create(tempPath))
{
    while (reader.Read())
    {
        if (reader.NodeType == XmlNodeType.Element && reader.Name == "xref" 
            && reader.GetAttribute("ref-type") == "disp-formula")
        {
            string rid = reader.GetAttribute("rid");
            if (rid != null && ridMap.TryGetValue(rid, out string newRid))
            {
                // 写入替换后的节点
                writer.WriteStartElement("xref");
                writer.WriteAttributeString("ref-type", "disp-formula");
                writer.WriteAttributeString("rid", newRid);
                writer.WriteRaw(reader.ReadInnerXml());
                writer.WriteEndElement();
                continue;
            }
        }
        // 其他节点直接复制
        writer.WriteNode(reader, true);
    }
}

// 替换原文件
File.Delete(filePath);
File.Move(tempPath, filePath);

内容的提问来源于stack exchange,提问作者Don_B

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:56:28