説明は長い方が少しわかります。私は巨大なXMLファイルを処理し検証し、検証エラーを引き起こしたノードを記録し、次のノードの処理を続行したいと思います。 XMLファイルの簡略版を以下に示します。C#の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>
は、私は現在、私はXML処理コードで扱う例外をスローしたXMLReaderとのValidationEventHandlerを使用してXmlSchemaValidationExceptionから回復することができています。しかし、場合によってはXMLExceptionがトリガーされているため、プロセスが終了することがあります。
コードの次のスニペットは、私が使用している現在の構造を示しています。それは面倒であり、コード改善の提案も歓迎です。 XMLSchemaValidationExceptionが検出されると
// 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);
}
finallyブロックは、(近い起動する)と、元のXMLReaderがサブツリーの上に位置するendElement、したがって最終的processAにブロックされている次のノードAの処理につながります
ただし、XMlExceptionが発生した場合、closeメソッドを呼び出すと、元のリーダーがサブツリーのEndElementノードに配置されず、InvalidOperationExceptionがスローされます。
私はスキップ、ReadToXYZ()メソッドのようなメソッドを使用しようとしましたが、これらは例外をトリガーしたノードで呼び出されたとき必ずInvalidOperationExceptionのXMLExcpetionにつながります。
以下は、ReadSubTreeメソッドに関するMSDNの抜粋です。新しいXMLReaderが が閉じられた場合
、オリジナルXMLReaderが サブツリーのするendElementノード上に配置 あろう。あなたは book要素の開始タグに ReadSubtreeメソッドを呼び出した場合はこのように、読まれていて、新しいXmlReaderの が閉じられた サブツリー後、元 たXmlReaderはの終了タグ 上に配置されていますブック要素。
注:これは.Net 3.5を使用できませんが、.Net 3.5の提案は大歓迎です。
例外を処理して、コードを簡潔にするためにコードを削除しました。私は最終的にブロックで他のいくつかのアクションを実行する必要があるので、私は "使用"ブロックを使用する利点を見た。 – welllifeisunfair