J'essaie de lire le document Xml suivant aussi vite que possible et de laisser des classes supplémentaires gérer la lecture de chaque sous-bloc.
<ApplicationPool>
<Accounts>
<Account>
<NameOfKin></NameOfKin>
<StatementsAvailable>
<Statement></Statement>
</StatementsAvailable>
</Account>
</Accounts>
</ApplicationPool>
Cependant, j'essaye d'utiliser l'objet XmlReader pour lire chaque compte et par la suite le "StatementsAvailable". Proposez-vous d'utiliser XmlReader.Read et vérifier chaque élément et le gérer?
J'ai pensé à séparer mes classes pour gérer correctement chaque nœud. Donc, il y a une classe AccountBase qui accepte une instance XmlReader qui lit le NameOfKin et plusieurs autres propriétés sur le compte. Ensuite, je voulais interagir à travers les déclarations et laisser une autre classe se renseigner sur la déclaration (et l'ajouter ensuite à un IList).
Jusqu'à présent, j'ai fait la partie "par classe" en faisant XmlReader.ReadElementString () mais je ne peux pas m'entraîner sur la manière de dire au pointeur de se déplacer vers l'élément StatementsAvailable et de me laisser les parcourir et laisser une autre classe lire chacune de ces propriétés .
Cela semble facile!
Réponses:
D'après mon expérience,
XmlReader
il est très facile de trop lire accidentellement. Je sais que vous avez dit que vous vouliez le lire le plus rapidement possible, mais avez-vous essayé d' utiliser un modèle DOM à la place? J'ai trouvé que LINQ to XML rend le travail XML beaucoup plus facile.Si votre document est particulièrement volumineux, vous pouvez combiner
XmlReader
et LINQ to XML en créant unXElement
from anXmlReader
pour chacun de vos éléments "externes" de manière continue: cela vous permet d'effectuer la plupart des travaux de conversion en LINQ to XML, mais vous n'avez encore besoin que une petite partie du document en mémoire à tout moment. Voici un exemple de code (légèrement adapté de ce billet de blog ):J'ai déjà utilisé cela pour convertir les données utilisateur de StackOverflow (ce qui est énorme) dans un autre format - cela fonctionne très bien.
EDIT de radarbob, reformaté par Jon - bien qu'il ne soit pas tout à fait clair de quel problème de "lecture trop loin" il est fait référence ...
Cela devrait simplifier l'imbrication et résoudre le problème "une lecture trop loin".
Cela résout le problème de "lecture trop loin" car il implémente le modèle de boucle while classique:
la source
if(reader.Name == elementName)
pourwhile(reader.Name == elementName)
résoudre le problème signalé par pbz?SimpleStreamAxis()
ignorera les éléments lorsque le XML n'est pas indenté, carNode.ReadFrom()
positionne le lecteur sur le nœud suivant après le chargement de l'élément - qui sera ignoré par le prochain inconditionnelRead()
. Si le nœud suivant est un espace blanc, tout va bien. Sinon, non. Pour les versions sans ce problème, voir ici , ici ou ici .Trois ans plus tard, peut-être avec l'accent renouvelé sur les données WebApi et xml, je suis tombé sur cette question. Comme je suis enclin à suivre Skeet depuis un avion sans parachute, et voyant son code initial doublement corraboré par l'article de l'équipe MS Xml ainsi qu'un exemple dans BOL Streaming Transform of Large Xml Docs , j'ai très vite négligé les autres commentaires , plus spécifiquement de «pbz», qui a souligné que si vous avez les mêmes éléments par nom successivement, tous les autres sont ignorés à cause de la double lecture. Et en fait, les articles du blog BOL et MS analysaient tous deux des documents sources avec des éléments cibles imbriqués plus profondément que le deuxième niveau, masquant cet effet secondaire.
Les autres réponses abordent ce problème. Je voulais juste proposer une révision légèrement plus simple qui semble bien fonctionner jusqu'à présent, et prend en compte le fait que le xml peut provenir de différentes sources, pas seulement d'un uri, et donc l'extension fonctionne sur le XmlReader géré par l'utilisateur. La seule hypothèse est que le lecteur est dans son état initial, sinon le premier 'Read ()' pourrait avancer au-delà d'un nœud souhaité:
la source
else Read()
s'applique aux deux. Merci d'avoir attrapé ça.Nous faisons ce genre d'analyse XML tout le temps. La clé est de définir où la méthode d'analyse laissera le lecteur à la sortie. Si vous laissez toujours le lecteur sur l'élément suivant après l'élément qui a été lu en premier, vous pouvez lire en toute sécurité et de manière prévisible dans le flux XML. Donc, si le lecteur indexe actuellement l'
<Account>
élément, après l'analyse, le lecteur indexera la</Accounts>
balise de fermeture.Le code d'analyse ressemble à ceci:
La
Statements
classe lit juste dans le<StatementsAvailable>
nœudLa
Statement
classe se ressemblerait beaucoupla source
Pour les sous-objets,
ReadSubtree()
vous donne un lecteur xml limité aux sous-objets, mais je pense vraiment que vous faites cela à la dure. Sauf si vous avez des exigences très spécifiques pour gérer des fichiers XML inhabituels / imprévisibles, utilisezXmlSerializer
(peut-être associé àsgen.exe
si vous le souhaitez vraiment).XmlReader
est ... délicat. Contraste avec:la source
L'exemple suivant navigue dans le flux pour déterminer le type de nœud actuel, puis utilise XmlWriter pour générer le contenu XmlReader.
L'exemple suivant utilise les méthodes XmlReader pour lire le contenu des éléments et des attributs.
la source
Vous pouvez parcourir xmlnode et obtenir les données ...... C # XML Reader
la source
Je ne suis pas expérimenté. Mais je pense que XmlReader est inutile. C'est très difficile à utiliser.
XElement est très simple à utiliser.
Si vous avez besoin de performances (plus rapides), vous devez changer le format de fichier et utiliser les classes StreamReader et StreamWriter.
la source