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

来自:博客园
时间:2024-01-31
阅读:

问题描述:

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

解析PPTX 遇到异常:“\b”(十六进制值 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); } } } } } }
返回顶部
顶部