Ich versuche, das folgende XML-Dokument so schnell wie möglich zu lesen und zusätzliche Klassen das Lesen jedes Unterblocks verwalten zu lassen.
<ApplicationPool>
<Accounts>
<Account>
<NameOfKin></NameOfKin>
<StatementsAvailable>
<Statement></Statement>
</StatementsAvailable>
</Account>
</Accounts>
</ApplicationPool>
Ich versuche jedoch, das XmlReader-Objekt zum Lesen jedes Kontos und anschließend der "StatementsAvailable" zu verwenden. Schlagen Sie vor, XmlReader.Read zu verwenden, jedes Element zu überprüfen und damit umzugehen?
Ich habe darüber nachgedacht, meine Klassen zu trennen, um jeden Knoten richtig zu behandeln. Es gibt also eine AccountBase-Klasse, die eine XmlReader-Instanz akzeptiert, die den NameOfKin und mehrere andere Eigenschaften des Kontos liest. Dann wollte ich die Anweisungen durchgehen lassen und eine andere Klasse sich über die Anweisung ausfüllen lassen (und sie anschließend einer IList hinzufügen).
Bisher habe ich den Teil "pro Klasse" mit XmlReader.ReadElementString () ausgeführt, aber ich kann nicht trainieren, wie der Zeiger angewiesen wird, zum Element StatementsAvailable zu wechseln, und ich kann sie durchlaufen und jede dieser Eigenschaften von einer anderen Klasse lesen lassen .
Klingt einfach!
Antworten:
Ich habe die Erfahrung gemacht,
XmlReader
dass es sehr leicht ist, versehentlich zu viel zu lesen. Ich weiß, dass Sie gesagt haben, Sie möchten es so schnell wie möglich lesen, aber haben Sie stattdessen versucht , ein DOM-Modell zu verwenden? Ich habe festgestellt, dass LINQ to XML die Arbeit mit XML erheblich vereinfacht.Wenn Ihr Dokument besonders riesig ist, können Sie kombinieren ,
XmlReader
um XML und LINQ durch eine SchaffungXElement
von einemXmlReader
für jeden Ihrer „äußeren“ Elemente in einer Streaming - Weise: auf diese Weise können Sie die meisten der Umbauarbeiten in LINQ to XML tun, aber immer noch nur Notwendigkeit jeweils ein kleiner Teil des Dokuments im Speicher. Hier ist ein Beispielcode (leicht angepasst aus diesem Blog-Beitrag ):Ich habe dies verwendet, um die StackOverflow-Benutzerdaten (die enorm sind) in ein anderes Format zu konvertieren - es funktioniert sehr gut.
EDIT von Radarbob, neu formatiert von Jon - obwohl nicht ganz klar ist, auf welches Problem "zu weit lesen" Bezug genommen wird ...
Dies sollte die Verschachtelung vereinfachen und das Problem "zu weit lesen" beheben.
Dies behebt das Problem "zu weit lesen", da es das klassische while-Schleifenmuster implementiert:
quelle
if(reader.Name == elementName)
,while(reader.Name == elementName)
um das von pbz aufgezeigte Problem zu beheben?SimpleStreamAxis()
überspringt die aktuelle Version von Elemente, wenn das XML nicht eingerückt ist, daNode.ReadFrom()
der Leser am nächsten Knoten nach dem Laden des Elements positioniert wird - was von der nächsten bedingungslosen Version übersprungen wirdRead()
. Wenn der nächste Knoten ein Leerzeichen ist, ist alles in Ordnung. Sonst nicht. Versionen ohne dieses Problem finden Sie hier , hier oder hier .Drei Jahre später, vielleicht mit dem erneuten Schwerpunkt auf WebApi- und XML-Daten, stieß ich auf diese Frage. Da ich codeweise dazu neige, Skeet ohne Fallschirm aus einem Flugzeug zu folgen, und seinen ursprünglichen Code, der durch den Artikel des MS Xml-Teams sowie ein Beispiel in der BOL- Streaming-Transformation großer XML-Dokumente doppelt herausgearbeitet wurde , sehr schnell übersehen habe, habe ich die anderen Kommentare sehr schnell übersehen , insbesondere von 'pbz', der darauf hinwies, dass, wenn Sie die gleichen Elemente nacheinander nach Namen haben, jedes andere wegen des doppelten Lesens übersprungen wird. Tatsächlich analysierten die BOL- und MS-Blog-Artikel Quelldokumente mit Zielelementen, die tiefer als die zweite Ebene verschachtelt waren, und maskierten diesen Nebeneffekt.
Die anderen Antworten befassen sich mit diesem Problem. Ich wollte nur eine etwas einfachere Revision anbieten, die bisher gut zu funktionieren scheint, und berücksichtigt, dass die XML-Datei möglicherweise aus verschiedenen Quellen stammt, nicht nur aus einer Uri. Daher funktioniert die Erweiterung auf dem vom Benutzer verwalteten XmlReader. Die eine Annahme ist, dass sich der Leser in seinem Anfangszustand befindet, da andernfalls das erste 'Read ()' an einem gewünschten Knoten vorbeiziehen könnte:
quelle
else Read()
für beide gilt. Danke, dass du das verstanden hast.Wir führen diese Art der XML-Analyse ständig durch. Der Schlüssel definiert, wo die Analysemethode den Leser beim Beenden verlässt. Wenn Sie den Reader immer auf dem nächsten Element belassen, das dem zuerst gelesenen Element folgt, können Sie den XML-Stream sicher und vorhersehbar einlesen. Wenn der Reader das
<Account>
Element gerade indiziert , indiziert der Reader nach dem Parsen das</Accounts>
schließende Tag.Der Parsing-Code sieht ungefähr so aus:
Die
Statements
Klasse liest nur den<StatementsAvailable>
Knoten einDie
Statement
Klasse würde sehr ähnlich aussehenquelle
Für Unterobjekte,
ReadSubtree()
gibt Ihnen einen XML-Leser auf die Unterobjekte beschränkt, aber ich wirklich denke , dass man dies auf die harte Art und Weise tun. Verwenden Sie diese Option (möglicherweise in Verbindung mit, wenn Sie wirklich möchten), es sei denn, Sie haben sehr spezielle Anforderungen für den Umgang mit ungewöhnlichen / nicht vorhersehbaren XML-Dateien .XmlSerializer
sgen.exe
XmlReader
ist ... schwierig. Im Gegensatz zu:quelle
Das folgende Beispiel navigiert durch den Stream, um den aktuellen Knotentyp zu ermitteln, und verwendet dann XmlWriter, um den XmlReader-Inhalt auszugeben.
Im folgenden Beispiel werden die XmlReader-Methoden verwendet, um den Inhalt von Elementen und Attributen zu lesen.
quelle
Sie können xmlnode durchlaufen und die Daten abrufen ...... C # XML Reader
quelle
Ich bin nicht erfahren. Aber ich denke, XmlReader ist unnötig. Es ist sehr schwer zu bedienen.
XElement ist sehr einfach zu bedienen.
Wenn Sie Leistung (schneller) benötigen, müssen Sie das Dateiformat ändern und die Klassen StreamReader und StreamWriter verwenden.
quelle