当前位置 : 主页 > 编程语言 > c语言 >

在C#中优雅地处理XML文件中的验证错误

来源:互联网 收集:自由互联 发布时间:2021-06-25
描述有点长,请耐心等待.我想处理并验证一个巨大的 XML文件,并记录触发验证错误的节点并继续处理下一个节点. XML文件的简化版本如下所示. 我想要执行的是遇到任何验证错误处理节点
描述有点长,请耐心等待.我想处理并验证一个巨大的 XML文件,并记录触发验证错误的节点并继续处理下一个节点. XML文件的简化版本如下所示.

我想要执行的是遇到任何验证错误处理节点’A’或其子节点(XMLException和XmlSchemaValidationException)我想停止处理当前节点记录节点’A’的错误和XML并继续下一步节点’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>

我目前能够通过使用带有XMLReader的ValidationEventHandler从XmlSchemaValidationException中恢复,这会抛出我在XML Processing代码中处理的Exception.但是在某些情况下,触发XMLException会导致进程终止.

以下代码片段说明了我正在使用的当前结构;它很混乱,也欢迎代码改进建议.

// 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中的finally块将导致处理下一个节点A.

但是,遇到XMlException时,调用close方法不会将原始读取器放在子树的EndElement节点上,而是抛出InvalidOperationException.

我尝试使用诸如skip,ReadToXYZ()方法之类的方法,但是当在触发异常的任何节点上调用时,这些方法总是导致InvalidOperationException的XMLExcpetion.

以下是MSDN关于ReadSubTree方法的摘录.

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建议.

看到这个问题:
XML Parser Validation Report

您需要区分格式良好的xml(它遵循实际xml所需的规则)和有效的xml(遵循特定xml架构给出的附加规则).从规格:

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工具都需要非常密切地遵循该规范,因此如果存在格式错误,则不会继续处理.我提供的链接可能会为您提供一些替代方案.

网友评论