C#遍历XmlDocument子节点反序列化报路径非法字符问题求解
错误产生原因
抛出"路径中存在非法字符"异常的核心原因是XmlReader.Create的重载匹配错误:
element.OuterXml本身已经是字符串类型,不需要额外调用ToString(),它返回的是当前<message>节点的完整XML片段。XmlReader.Create有一个重载接收字符串类型的文件路径参数,当你直接传入XML片段字符串时,方法会默认把这段内容当作磁盘文件路径去尝试读取文件,而XML内容里的<、>、/、空格等字符都是Windows文件路径明令禁止的非法字符,因此直接触发异常。- 即使你修正参数传递问题,当前代码还存在序列化映射的隐患:默认的XmlSerializer会将类名作为根节点匹配依据,且需要明确字段和XML节点的映射关系,否则可能出现反序列化后字段值为默认值的问题。
直接基于XmlElement反序列化的实现方案
不需要调用ToString(),也不需要将节点转为XML字符串二次解析,直接使用XmlNodeReader(XmlReader的派生类)读取XmlElement节点即可完成反序列化,性能更高也不会出现参数类型匹配错误,修正后的代码如下:
using System; using System.Xml; using System.Xml.Serialization; class Program { static void Main(string[] args) { XmlReaderSettings readerSettings = new XmlReaderSettings(); readerSettings.IgnoreComments = true; // 初始化序列化器,显式指定根节点为message,匹配单个<message>节点结构 XmlSerializer serializer = new XmlSerializer(typeof(Message), new XmlRootAttribute("message")); using (XmlReader xmlReader = XmlReader.Create(@"..\..\test.xml", readerSettings)) { XmlDocument doc = new XmlDocument(); doc.Load(xmlReader); foreach (XmlElement element in doc.DocumentElement.ChildNodes) { Console.WriteLine($"id : {element.SelectSingleNode("id").InnerText}, message : {element.SelectSingleNode("text").InnerText}"); // 直接传入XmlElement构造XmlNodeReader,无需转字符串 using (XmlNodeReader nodeReader = new XmlNodeReader(element)) { Message message = (Message)serializer.Deserialize(nodeReader); // 此处可直接使用反序列化得到的message对象 } } } Console.ReadLine(); } } public class Message { // 显式映射XML节点和类字段,避免命名/大小写匹配问题 [XmlElement("id")] public int id; [XmlElement("text")] public string text; }
补充说明:
- 所有实现了
IDisposable的XML读取相关对象都用using块包裹,可自动释放资源,避免内存泄漏。 - 如果一定要基于
OuterXml的字符串内容反序列化,需要用StringReader包裹字符串后传入,避免触发文件路径的重载,写法为serializer.Deserialize(new StringReader(element.OuterXml)),但该方案需要额外做字符串到内存流的转换,性能弱于直接使用XmlNodeReader的方案。
内容的提问来源于stack exchange,提问作者Lucas Weibel
相关产品推荐
相关产品推荐

