在C#中使用未关闭的标记读取XML

我有一个程序,它运行测试并生成一个包含所有结果的网格视图,以及一个XML日志文件。 该程序还具有加载日志以复制网格视图的function。

由于程序在执行时写入日志文件,如果崩溃,日志文件将缺少结束标记。 我仍然希望能够加载这些XML文件,因为仍有许多有价值的数据可以帮助我找出导致崩溃的原因。

我想可能会通过XML文件并关闭任何未关闭的XML标记,或者编写某种“Dirty”XML读取器,假装每个标记都已关闭。 关于我能做什么或如何进行的任何想法?

编辑:

   ... ... ...   ... ... !-- Crash happens here --! 

从此我仍然希望生产

  Child Foo Bar Baz One ... ... ... Two ... ... / 

据推测它一直有效,直到它被截断…所以使用XmlReader可以工作…只是准备好处理它到达截断点时爆炸。

现在XmlReader API并不是非常令人愉快(IMO)所以你可能想要转移到一些有趣数据的开头(这本身就必须完成),然后调用XNode.ReadFrom(XmlReader)方法来获取该数据以简单易用的forms。 然后移动到下一个元素的开头并执行相同的操作,等等。

示例代码:

 using System; using System.Linq; using System.Xml; using System.Xml.Linq; class Program { static void Main(string[] args) { using (XmlReader reader = XmlReader.Create("test.xml")) { while (true) { while (reader.NodeType != XmlNodeType.Element || reader.LocalName != "Child") { if (!reader.Read()) { Console.WriteLine("Finished!"); } } XElement element = (XElement) XNode.ReadFrom(reader); Console.WriteLine("Got child: {0}", element.Value); } } } } 

示例XML:

   First child Second child Broken 

样本输出:

有孩子:第一个孩子有孩子:第二个孩子

 Unhandled Exception: System.Xml.XmlException: Unexpected end of file has occurred The following elements are not closed: Child, Parent, Root. Line 5, position 18. at System.Xml.XmlTextReaderImpl.Throw(String res, String arg) at System.Xml.XmlTextReaderImpl.ParseElementContent() at System.Xml.Linq.XContainer.ReadContentFrom(XmlReader r) at System.Xml.Linq.XContainer.ReadContentFrom(XmlReader r, LoadOptions o) at System.Xml.Linq.XElement.ReadElementFrom(XmlReader r, LoadOptions o) at System.Xml.Linq.XNode.ReadFrom(XmlReader reader) at Program.Main(String[] args) 

显然你想要捕获exception,但你可以看到它设法正确读取前两个元素。

作为最后的手段,根据您正在做的事情,您可以使用HTML阅读器,如HtmlAgilityPack ( Nuget页面 )或SGMLReader 。 SGMLReader实际上会将它转换为XmlDocument,因此可能更符合您的要求。

当然,HTML不是XML,因此您可以获得使用此方法时获得的内容。

框架中没有这样的东西,默认情况下没有这样做,也没有一个好的解决方案可以以某种方式解析通用的无效xml。

你可以做的最明智的事情是在开始阅读之前修复XML。 由于只有结束被切断,你应该能够找出所有打开的标签并关闭它们。