2010-09-28 5 views
0

Je cherche autre chose que XmlReader.Rechercher un fichier XML sans le charger dans la mémoire?

Je souhaite appliquer une requête et charger uniquement les données nécessaires.

En fait, je veux charger le moins possible de xml. Peut-être qu'une sorte d'utilitaire/classe XQuery pourrait faire l'affaire.

+2

Urm, XmlReader ne charge pas les données qu'il ne le fait pas besoin, dans le sens où, contrairement à XmlDocument, il ne conserve pas un état complet en mémoire à un moment donné, à sa lecture, il ne conserve qu'un état suffisant pour savoir où il se trouve. Cependant, pour trouver la partie correcte du XML, vous devez en lire une partie, sinon vous pourriez écrire une expression rationnelle sale et l'analyser de cette façon. – tyranid

Répondre

3

Vous pouvez mélanger XmlReader avec LINQ en XML pour obtenir le meilleur des deux mondes. L'astuce consiste à utiliser LINQ to XML pour charger uniquement les nœuds internes dans la mémoire.

Par exemple, supposons que vous avez un fichier XML avec la structure suivante:

<log> 
    <logentry id="1"> 
    <date>...</date> 
    <source>...</source> 
    ... 
    </logentry> 
    ... 
</log> 

Imaginez il y a un million d'éléments de logentry, et que vous voulez trouver les éléments où l'élément source contient une chaîne particulière. Tout d'abord, écrire la méthode suivante:

Enumerable<LogEntry> ReadLogEntries (XmlReader r) 
{ 
    r.ReadStartElement ("log"); 
    while (r.Name == "logentry") 
    { 
    XElement logEntry = (XElement) XNode.ReadFrom (r); 
    yield return new LogEntry 
    { 
     ID = (int) logEntry.Attribute ("id"), 
     Date = (DateTime) logEntry.Element ("date"), 
     Source = (string) logEntry.Element ("source") 
    } 
    } 
    r.ReadEndElement(); 
} 

class LogEntry 
{ 
    public int ID; 
    public DateTime Date; 
    public string Source; 
} 

Ensuite, vous pouvez interroger le fichier XML (sans le charger tous en mémoire) comme suit:

from l in ReadLogEntries (reader) 
where l.Source.Contains ("foo") 
select new { l.ID, l.Date } 
+1

+1 très cool, donnant des valeurs signifierait .net créerait un énumérateur et la requête serait paresseux droit? Donc si foo était l'élément 2, il ne chargerait que 2 éléments!? – gideon

+0

Je suis curieux de connaître la réponse à la question de Gideon. @ Joe Albahari pourriez-vous répondre? – Freestyle076

+0

Correct. La requête est paresseuse. –

Questions connexes