2017-07-21 3 views
2

Je voudrais implémenter un code qui désérialise un XML dans une liste d'objets. J'ai trouvé un problème dans le code où le while lit forward afin que tous les autres nœuds soient ignorés. Quelle est la bonne façon de vérifier la présence d'un noeud suivant dans un fichier XML à implémenter dans la boucle while de ce code?Comment vérifier si un autre nœud existe dans un fichier XML sans lire - C#

private Task<List<TAxEntity>> Deserialize(XmlReader reader) 
    { 
     var deserializer = new XmlSerializer(typeof(TAxEntity)); 
     var entities = new List<TAxEntity>(); 

     do 
     { 
      using (var stringReader = new StringReader(reader.ReadOuterXml())) 
      { 
       var entity = (TAxEntity)deserializer.Deserialize(stringReader); 

       entities.Add(entity); 
      } 
     } 
     while (reader.ReadToNextSibling(EntityElementName)); 

     return Task.FromResult(entities); 
    } 
+1

Le saut est causé par ReadToNextSibling. Trouvez un autre moyen de savoir quand vous êtes à la fin, car ReadOuterXml avance déjà votre flux. – hoodaticus

+1

Oui, je l'ai réalisé, c'est pourquoi je suis à la recherche d'une autre solution pour aller de l'avant sans lire. Merci! –

+2

'while (lecteur.read()) {...}'? – PiLHA

Répondre

0

Pour vérifier qu'un XmlReader est déjà correctement positionné, vous pouvez vérifier si reader.NodeType == XmlNodeType.Element et reader.Name == EntityElementName. Ensuite, si le lecteur est déjà correctement positionné, ne numérisez pas vers l'avant en utilisant ReadToNextSibling().

Cependant, il y a quelques améliorations à apporter à votre algorithme:

  1. Au lieu de vérifier la reader.Name correcte, vérifiez si la LocalName et NamespaceURI sont comme prévu, et sinon, appelez reader.ReadToNextSibling(string localName,string namespaceURI). Cela évite le codage en dur des préfixes d'espace de noms, qui est un bug to be avoided. Au lieu de ReadOuterXml(), appelez reader.ReadSubtree() et passez le lecteur retourné directement à deserializer.Deserialize(). Votre algorithme actuel analyse le XML, le reformate en une deuxième chaîne XML, puis analyse cette chaîne une seconde fois. L'utilisation de ReadSubtree() permet au XmlSerializer de diffuser un élément imbriqué directement à partir du XmlReader entrant et évite ainsi cette analyse et reformatage supplémentaires.

Mettre tout cela ensemble, vous pouvez introduire la méthode d'extension de niveau inférieur suivant:

public static class XmlReaderExtensions 
{ 
    public static IEnumerable<TElement> DeserializeSequence<TElement>(this XmlReader reader, string localEntityElementName, string namespaceURI) 
    { 
     if (reader == null) 
      throw new ArgumentNullException(); 
     var deserializer = new XmlSerializer(typeof(TElement)); 
     while ((reader.NodeType == XmlNodeType.Element && reader.LocalName == localEntityElementName && reader.NamespaceURI == namespaceURI) 
      || reader.ReadToNextSibling(localEntityElementName, namespaceURI)) 
     { 
      // Using ReadSubtree instead of ReadOuterXml() avoids having do parse, reformat, then parse the formatted XML a second time 
      // by reading directly from the current stream only once. 
      TElement element; 
      using (var subReader = reader.ReadSubtree()) 
      { 
       element = (TElement)deserializer.Deserialize(subReader); 
      } 
      // Consume the EndElement also (or move past the current element if reader.IsEmptyElement). 
      reader.Read(); 
      yield return element; 
     } 
    } 
} 

Et modifier votre méthode Deserialize() être comme suit:

private Task<List<TAxEntity>> Deserialize(XmlReader reader) 
    { 
     var entities = reader.DeserializeSequence<TAxEntity>(EntityElementName, "" /* Pass the correct namespace here */).ToList(); 

     return Task.FromResult(entities); 
    }  

Sample .Net fiddle.

Notez que tout code XmlReader manuel doit être l'unité testée à la fois XML échancrée et non indenté, car les bogues qui impliquent des noeuds à sauter sont parfois masqués lors de l'analyse XML dentelée (parce que les nœuds blancs se sautée.)

+0

Cela a résolu mon problème, merci beaucoup! –