解析PPTX 遇到异常:“\b”(十六进制值 0x08)是无效的字符。

问题描述:#

通过DocumentFormat.OpenXml解析PPTX文件时遇到异常:“\b”(十六进制值 0x08)是无效的字符,查看文件发现存在乱码,乱码的十六进制值刚好时异常中提到的0x08


原因分析:#

网上有很多关于这类xml遇到无效字符异常的文章,其原因是xml中包含了不可打印的控制字符,解决办法是正则匹配替换这类字符。正则匹配的代码如下:

string r = "[\x00-\x08\x0B\x0C\x0E-\x1F\x26]";
return Regex.Replace(brokenXml, r, "", RegexOptions.Compiled);

 


解决方案:#

原因和处理方式都有了,那么问题来了,加载PPTX文件的时候就抛出异常了,在什么时候替换xml中的控制字符呢?想起OpenXmlPowerTools的源码中关于处理文档中包含不合法的uri的代码,于是如法炮制,在加载页面slide的时候捕获XmlException类型的异常,在异常中修复xml内容

try
{
    .......
}
catch (XmlException xe)
{
	using (FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite))
	{
		XmlFixer.FixInvalidXml(fs, brokenXml =>
		{
			string r = "[\x00-\x08\x0B\x0C\x0E-\x1F\x26]";
			return Regex.Replace(brokenXml, r, "", RegexOptions.Compiled);
		});
	}
	return ReadPPTXText(filePath);
}


    public static class XmlFixer
    {
        public static void FixInvalidXml(Stream fs,Func invalidXmlHandler)
        {
            using (ZipArchive za = new ZipArchive(fs, ZipArchiveMode.Update))
            {
                bool IsInvalidXml = false;
                for (int i=0;i< za.Entries.Count;i++)
                {
                    var entry = za.Entries[i];
                    if (!entry.Name.EndsWith(".xml"))
                        continue;
                    bool replaceEntry = false;
                    XDocument entryXDoc = null;
                    using (var entryStream = entry.Open())
                    {
                        try
                        {
                            if (IsInvalidXml)
                            {
                                string content;
                                using (StreamReader sr = new StreamReader(entryStream))
                                {
                                    content = invalidXmlHandler(sr.ReadToEnd());
                                }
                                entryXDoc = XDocument.Parse(content);
                                IsInvalidXml = false;
                                replaceEntry = true;
                            }
                            else
                            {
                                entryXDoc = XDocument.Load(entryStream);
                                IsInvalidXml = false;
                            }
                        }
                        catch (XmlException xex)
                        {
                            i--;
                            IsInvalidXml = true;
                        }
                    }
                    if (replaceEntry)
                    {
                        var fullName = entry.FullName;
                        entry.Delete();
                        var newEntry = za.CreateEntry(fullName);
                        using (StreamWriter writer = new StreamWriter(newEntry.Open()))
                        using (XmlWriter xmlWriter = XmlWriter.Create(writer))
                        {
                            entryXDoc.WriteTo(xmlWriter);
                        }
                    }
                }
            }
        }
    }

作者:czwy

出处:https://www.cnblogs.com/czwy/p/16964442.html

版权:本作品采用「署名-相同方式共享 4.0 国际」许可协议进行许可。

posted @   czwy  阅读(59)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)
more_horiz
keyboard_arrow_up light_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示