La description est peu sur le côté long s'il vous plaît ours avec moi. Je voudrais traiter et valider un énorme fichier XML et enregistrer le noeud qui a déclenché l'erreur de validation et continuer le traitement du noeud suivant. Une version simplifiée du fichier XML est présentée ci-dessous. Ce que je voudrais faire est de rencontrer un noeud de traitement d'erreur de validation 'A' ou ses enfants (XMLException et XmlSchemaValidationException) Je voudrais arrêter de traiter le noeud courant consigner l'erreur et le XML pour le noeud 'A' et déplacer sur le prochain noeud «A».gérer gracieusement les erreurs de validation dans un fichier XML en C#
<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>
Je suis actuellement en mesure de récupérer de la XmlSchemaValidationException en utilisant un ValidationEventHandler avec XMLReader qui jette une exception que je gère dans le code de traitement XML. Cependant, dans certains cas, XMLException est déclenché ce qui conduit à la fin du processus.
Les extraits suivants du code illustrent la structure actuelle que j'utilise; il est en désordre et les suggestions d'amélioration du code sont également les bienvenues.
// 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);
}
Lorsqu'un XMLSchemaValidationException est rencontré le bloc finalement invoquera close() et l'XMLReader d'origine est positionné sur le EndElement du sous-arbre et par conséquent le bloc finally en processa conduira à un traitement du nœud suivant A.
Toutefois, lorsqu'une exception XMlException est rencontrée, l'invocation de la méthode close ne positionne pas le lecteur d'origine sur le noeud EndElement du sous-arbre et une exception InvalidOperationException est en cours de lancement.
J'ai essayé d'utiliser des méthodes telles que skip, ReadToXYZ(), mais celles-ci conduisent invariablement à XMLExcpetion of InvalidOperationException lorsqu'elles sont invoquées sur n'importe quel noeud qui a déclenché une exception.
Voici un extrait de MSDN concernant la méthode ReadSubTree.
Lorsque le nouveau XmlReader a été fermé, sera positionné XmlReader d'origine sur le nœud de EndElement le sous-arbre. Ainsi, si vous avez appelé la méthode ReadSubtree sur la balise de début de l'élément livre, après le sous-arbre a été lu et le nouveau XmlReader a été fermé, le XmlReader original est placé sur la balise de fin du élément de livre.
Remarque: Je ne peux pas utiliser .Net 3.5 pour cela, cependant les suggestions de .Net 3.5 sont les bienvenues.
Je traitais l'exception supprimé le code pour le garder concis. J'ai besoin d'effectuer quelques autres actions dans le bloc finally, donc je n'ai vu aucun avantage à utiliser le bloc "using". – welllifeisunfair