在C#中的XML文件,妥善处理验证错误妥善处理、错误、文件、XML

2023-09-03 04:11:46 作者:仙女味慕斯

说明是在长边位,请多多包涵。我想处理和验证一个巨大的XML文件和日志由此引发的验证错误并继续处理下一个节点的节点。 XML文件的简化版本如下所示。

The description is bit on the longer side please bear with me. I would like to process and validate a huge XML file and log the node which triggered the validation error and continue with processing the next node. A simplified version of the XML file is shown below.

我想执行上遇到任何验证错误处理节点'A'或其子女(包括XMLException和XmlSchemaValidationException)我想停止处理当前节点记录错误和XML节点A,继续前进到下一个节点'A'。

What I would like to perform is on encountering any validation error processing node 'A' or its children (both XMLException and XmlSchemaValidationException) I would like to stop processing current node log the error and XML for node 'A' and move on to the next node 'A'.

<Root>
  <A id="A1">
     <B Name="B1">
        <C>
          <D Name="ID" >
            <E>Test Text 1</E>
          </D>
        <D Name="text" >
          <E>Test Text 1</E>
        </D>        
      </C>
    </B>
  </A>
  <A id="A2">
    <B Name="B2">
      <C>
        <D Name="id" >
          <E>Test Text 3</E>
        </D>
        <D Name="tab1_id"  >
          <E>Test Text 3</E>
        </D>
        <D Name="text" >
          <E>Test Text 3</E>
        </D>
      </C>
    </B>
</Root>

我目前能够从XmlSchemaValidationException使用的ValidationEventHandler用的XMLReader会抛出一个异常,我在处理XML处理code恢复。然而,对于一些情况XMLException被触发从而导致终止的过程。

I am currently able to recover from the XmlSchemaValidationException by using a ValidationEventHandler with XMLReader which throws a Exception that I handle in the XML Processing code. However for some cases XMLException is being triggered which leads to termination of the process.

的code以下片断描述了我使用的是目前的结构;这是混乱和code改进建议也欢迎。

The following snippets of the code illustrate the current structure I am using; it is messy and code improvement suggestions are also welcome.

    // Setting up the XMLReader
    XmlReaderSettings settings = new XmlReaderSettings();
    settings.ConformanceLevel = ConformanceLevel.Auto;
    settings.IgnoreWhitespace = true;
    settings.CloseInput = true;
    settings.IgnoreComments = true;
    settings.ValidationType = ValidationType.Schema;
    settings.Schemas.Add(null, "schema.xsd");
    settings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack);
    XmlReader reader = XmlReader.Create("Sample.xml", settings);   
    // Processing XML
    while (reader.Read())
    if (reader.NodeType == XmlNodeType.Element)
       if (reader.Name.Equals("A"))
         processA(reader.ReadSubtree());    	    
    reader.Close(); 
   // Process Node A
   private static void processA(XmlReader A){
    try{
       // Perform some book-keeping 
       // Process Node B by calling processB(A.ReadSubTree())           	
    }   
    catch (InvalidOperationException ex){

    }
    catch (XmlException xmlEx){

    } 
    catch (ImportException impEx){

    }
    finally{ if (A != null) A.Close(); }            
  }
  // All the lower level process node functions propagate the exception to caller.
  private static void processB(XmlReader B){
   try{
     // Book-keeping and call processC
   }
   catch (Exception ex){
    throw ex;
    }
   finally{ if (B != null) B.Close();}    
  } 
  // Validation event handler
  private static void ValidationCallBack(object sender, ValidationEventArgs e){
    String msg =  "Validation Error: " + e.Message +" at line " + e.Exception.LineNumber+
    	" position number "+e.Exception.LinePosition;
    throw new ImportException(msg);
  }

在XMLSchemaValidationException遇到finally块将调用close()和原始的XMLReader被定位在子树的EndElement,从而最终阻止processA将导致下一个节点A的处理。

When a XMLSchemaValidationException is encountered the finally block will invoke close() and the original XMLReader is being positioned on the EndElement of the subtree and hence the finally block in processA will lead to processing of the next node A.

然而,当XMlException遇到调用close方法是不定位的子树的的EndElement节点上原来的阅读器和一个InvalidOperationException正在扔了。

However when a XMlException is encountered invoking the close method is not positioning the original reader on the EndElement node of the subtree and an InvalidOperationException is being throw.

我试图用像跳跃的方法,ReadToXYZ()方法,但这些都不约而同地导致出现InvalidOperationException的XMLExcpetion引发异常的任何节点上调用时。

I tried to use methods like skip, ReadToXYZ() methods but these are invariably leading to XMLExcpetion of InvalidOperationException when invoked on any node that triggered an exception.

下面是从MSDN摘录有关ReadSubTree方法。

The following is a excerpt from MSDN regarding the ReadSubTree method.

在新的XmlReader已   关闭时,原始的XmlReader将   定位的的EndElement节点上   该子树。因此,如果你叫   在起始标签ReadSubtree方法   book元素,该子树后   已读和新的XmlReader   已被关闭,原   的XmlReader被定位在结束标记   这本书的元素。

When the new XmlReader has been closed, the original XmlReader will be positioned on the EndElement node of the sub-tree. Thus, if you called the ReadSubtree method on the start tag of the book element, after the sub-tree has been read and the new XmlReader has been closed, the original XmlReader is positioned on the end tag of the book element.

注:我不能使用的.Net 3.5对于这一点,但是NET 3.5的建议,欢迎。

Note: I cannot use .Net 3.5 for this, however .Net 3.5 suggestions are welcome.

推荐答案

看到这一问题: http://stackoverflow.com/questions/32505/xml-parser-validation-report

See this question: http://stackoverflow.com/questions/32505/xml-parser-validation-report

您需要的良好的区分的XML(它遵循是真正的XML所需要的规则)和有效的XML(遵循特定的XML模式给予额外的规则)。从规格:

You need to distinguish between well-formed xml (it follows the rules required to be real xml) and valid xml (follows additional rules given by a specific xml schema). From the spec:

在检测到致命错误,但是,处理器必须不能继续正常的处理(即,它必须停止传递字符数据的信息和关于文档的逻辑结构的应用程序以正常的方式)。

Once a fatal error is detected, however, the processor must not continue normal processing (i.e., it must not continue to pass character data and information about the document's logical structure to the application in the normal way).

是好还是坏,包含在Visual Studio中的XML工具需要遵循的规范关系十分密切,因此不会继续处理,如果有一个良好性错误。我提供的链接,可能会给你一些替代品。

For better or worse, the xml tools included with Visual Studio need to follow that spec very closely, and therefore will not continue processing if there is a well-formedness error. The link I provided might give you some alternatives.