【问题标题】:Reading XML with unclosed tags in C#在 C# 中读取带有未闭合标签的 XML
【发布时间】:2012-03-14 14:26:41
【问题描述】:

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

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

我在想也许可以浏览 XML 文件并关闭任何未关闭的 XML 标记,或者可能编写某种“脏”XML 阅读器来假装每个标记都已关闭。关于我可以做什么或应该如何进行的任何想法?

编辑:

<Root>
  <Parent>
     <Child Name="One">
        <Foo>...</Foo>
        <Bar>...</Bar>
        <Baz>...</Baz>
     </Child>
     <Child Name="Two">
        <Foo>...</Foo>
        <Bar>...</Bar>
 !-- Crash happens here --!

从此我仍然会期待生产

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

【问题讨论】:

  • 从技术上讲,带有未闭合标签的 XML 不是 XML,就像 VB 不是 C#一样。
  • 您尝试过 XmlReader 吗?这是最(唯一)宽容的阅读方式。
  • 此链接可能会有所帮助。 stackoverflow.com/questions/9681084/…
  • 您的意思是未闭合的标签,还是您的意思是缺少结束标签?那不是一回事。后者更容易修复。
  • @Mr Lister 编辑了这个问题,因为 XML 在 cmets 中不能很好地显示

标签: c# xml-parsing


【解决方案1】:

大概它在被截断之前都是有效的......所以使用XmlReader 可以工作......只要准备好在它到达截断点时处理它。

现在XmlReader API 不是非常令人愉快 (IMO),因此您可能想要移动到一些有趣数据的开头(这些数据本身必须是完整的),然后调用 XNode.ReadFrom(XmlReader) 方法来获取这些数据以易于使用的形式呈现。然后移动到下一个元素的开头并执行相同的操作,等等。

示例代码:

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:

<Root>
  <Parent>
    <Child>First child</Child>
    <Child>Second child</Child>
    <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)

所以很明显你想捕捉异常,但你可以看到它成功地读取了前两个元素。

【讨论】:

    【解决方案2】:

    作为最后的手段,根据您的操作,您可以使用 HTML 阅读器,例如 HtmlAgilityPack(Nuget page) 或 SGMLReader。 SGMLReader 实际上会将其转换为 XmlDocument,因此这可能是您正在寻找的更多内容。

    当然,HTML 不是 XML,所以当你使用这种方法时,你会得到你所得到的。

    【讨论】:

    • SGMLReader 的 +1,它有效。实际上也可以通过NuGet 下载。
    【解决方案3】:

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

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

    【讨论】:

    • OP 询问 如何 修复 XML
    • @HenkHolterman 我理解他的问题的方式是他想要关于他应该采取哪种方式的建议,我的建议是遵循他的第一直觉并在解析之前创建有效的 xml,而不是创建一个枯燥的阅读器,阅读这个问题再次得到相同的印象
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-10
    • 2017-02-17
    • 2021-12-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多