具有适当错误处理的XML读取(行号,原始文本等)

时间:2012-02-09 07:39:49

标签: c# xml xml-serialization xml-parsing

我想读一个相当大的xml文件。它足够小,适合记忆,但仍然很大。在读取XML时,它将根据XSD进行验证。但是,当使用读取数据进行系统中的进一步操作时,这不会阻止发生业务错误。当发生此类业务错误时(在XSD验证之后),我希望能够从我的xml中描述元素的开始和结束位置的行号列号。此外,在此上下文中,显示从文件中读取的输入xml 将是用户友好的。

使用 xsd.exe 我的代码生成了所有数据类,我使用

读取了xml
  using (var reader = new StringReader(content))
  {
    var errors = new List<string>();
    var settings = new XmlReaderSettings();
    settings.Schemas.Add("urn:import-schema", "Import.xsd");
    settings.ValidationEventHandler += (o, args) => errors.Add(args.Message);
    settings.ValidationType = ValidationType.Schema;

    using (XmlReader xr = XmlReader.Create(reader, settings))
    {
      var xs = new XmlSerializer(typeof(ImportRoot));
      var result = (ImportRoot) xs.Deserialize(xr);
      if (errors.Any())
        throw new Exception(string.Join("\n\n", errors));
      return result;
    }
  }
}

然而,我似乎无法找到我正在寻找的元信息。我也检查了XDocument课程。这里的元素似乎有一个Value属性是一个字符串。但这仍然不是我想要显示的所有信息。

2 个答案:

答案 0 :(得分:2)

不会从StringReader读取行号信息。如果您在StreamReader上使用FileStream,则可以获取该行号。

您要查找的其他元数据称为"Post Schema Validation Infoset"

答案 1 :(得分:0)

在ValidationEventHandler中查看args.Exception属性。它是XmlSchemaException类型,包含行号等。

您可以保留所有错误,然后再解析它们。

var errors = new List<ValidationEventArgs>();
....
settings.ValidationEventHandler += (o, args) => errors.Add(args);

可以通过将它们实现为自定义xslt函数来处理业务验证错误。见article。一旦有了实现IXsltContextFunction的函数,就可以在Invoke方法中检查XPathNavigator,了解提示,了解文档中的位置。

获得提示后,您可以将其与原始文档中的每一行进行比较。

几年前我做了类似的事情(除了行号),它的效果非常好。即使对于大型xml文档也是如此。