Saya mencoba membaca dokumen Xml berikut secepat mungkin dan membiarkan kelas tambahan mengatur pembacaan setiap sub blok.
<ApplicationPool>
<Accounts>
<Account>
<NameOfKin></NameOfKin>
<StatementsAvailable>
<Statement></Statement>
</StatementsAvailable>
</Account>
</Accounts>
</ApplicationPool>
Namun, saya mencoba menggunakan objek XmlReader untuk membaca setiap Akun dan selanjutnya "StatementsAvailable". Apakah Anda menyarankan menggunakan XmlReader.Read dan memeriksa setiap elemen dan menanganinya?
Saya telah memikirkan untuk memisahkan kelas saya untuk menangani setiap node dengan benar. Jadi ada kelas AccountBase yang menerima contoh XmlReader yang membaca NameOfKin dan beberapa properti lain tentang akun tersebut. Kemudian saya ingin menafsirkan melalui Pernyataan dan membiarkan kelas lain mengisi sendiri tentang Pernyataan (dan kemudian menambahkannya ke IList).
Sejauh ini saya memiliki bagian "per kelas" yang dilakukan dengan melakukan XmlReader.ReadElementString () tetapi saya tidak dapat mengetahui cara memberi tahu pointer untuk pindah ke elemen StatementsAvailable dan biarkan saya mengulanginya dan membiarkan kelas lain membaca masing-masing properti tersebut .
Kedengarannya mudah!
Jawaban:
Pengalaman saya
XmlReader
adalah sangat mudah untuk tidak sengaja membaca terlalu banyak. Saya tahu Anda pernah mengatakan ingin membacanya secepat mungkin, tetapi apakah Anda sudah mencoba menggunakan model DOM? Saya telah menemukan bahwa LINQ ke XML membuat XML bekerja jauh lebih mudah.Jika dokumen Anda sangat besar, Anda dapat menggabungkan
XmlReader
dan LINQ ke XML dengan membuatXElement
dari anXmlReader
untuk setiap elemen "luar" Anda secara streaming: ini memungkinkan Anda melakukan sebagian besar pekerjaan konversi dalam LINQ ke XML, tetapi tetap hanya perlu sebagian kecil dari dokumen dalam memori pada satu waktu. Berikut beberapa contoh kode (diadaptasi sedikit dari posting blog ini ):Saya telah menggunakan ini untuk mengonversi data pengguna StackOverflow (yang sangat besar) ke dalam format lain sebelumnya - ini bekerja dengan sangat baik.
EDIT dari radarbob, diformat ulang oleh Jon - meskipun tidak begitu jelas masalah "membaca terlalu jauh" mana yang dirujuk ...
Ini akan menyederhanakan pengumpulan dan mengatasi masalah "terlalu jauh".
Ini menangani masalah "membaca terlalu jauh" karena menerapkan pola loop sementara klasik:
sumber
if(reader.Name == elementName)
untukwhile(reader.Name == elementName)
memperbaiki masalah yang ditunjukkan oleh pbz?SimpleStreamAxis()
akan melewatkan elemen saat XML tidak menjorok ke dalam, karenaNode.ReadFrom()
menempatkan pembaca di node berikutnya setelah elemen dimuat - yang akan dilewati oleh tanpa syarat berikutnyaRead()
. Jika node berikutnya adalah spasi maka semuanya baik-baik saja. Kalau tidak, tidak. Untuk versi tanpa masalah ini lihat di sini , di sini atau di sini .Tiga tahun kemudian, mungkin dengan penekanan baru pada data WebApi dan xml, saya menemukan pertanyaan ini. Karena dengan kode saya cenderung mengikuti Skeet keluar dari pesawat tanpa parasut, dan melihat kode awalnya dikoraborasi dua kali oleh artikel tim MS Xml serta contoh di BOL Streaming Transform of Large Xml Docs , saya dengan cepat mengabaikan komentar lainnya , paling khusus dari 'pbz', yang menunjukkan bahwa jika Anda memiliki elemen yang sama dengan nama secara berurutan, setiap elemen lainnya akan dilewati karena pembacaan ganda. Dan faktanya, artikel blog BOL dan MS sama-sama mem-parse dokumen sumber dengan elemen target bersarang lebih dalam dari level kedua, menutupi efek samping ini.
Jawaban lain menjawab masalah ini. Saya hanya ingin menawarkan revisi yang sedikit lebih sederhana yang tampaknya bekerja dengan baik sejauh ini, dan memperhitungkan bahwa xml mungkin berasal dari sumber yang berbeda, bukan hanya uri, dan ekstensi berfungsi pada XmlReader yang dikelola pengguna. Asumsinya adalah bahwa pembaca berada dalam keadaan awalnya, karena jika tidak, 'Read ()' pertama mungkin maju melewati node yang diinginkan:
sumber
else Read()
berlaku untuk keduanya. Terima kasih sudah menangkapnya.Kami melakukan penguraian XML semacam ini sepanjang waktu. Kuncinya adalah menentukan di mana metode parsing akan membiarkan pembaca keluar. Jika Anda selalu meninggalkan pembaca pada elemen berikutnya setelah elemen yang pertama kali dibaca, maka Anda dapat membaca dengan aman dan dapat diprediksi di aliran XML. Jadi jika pembaca saat ini mengindeks
<Account>
elemen tersebut, setelah parsing pembaca akan mengindeks</Accounts>
tag penutup.Kode parsing terlihat seperti ini:
The
Statements
kelas hanya membaca di<StatementsAvailable>
simpulThe
Statement
kelas akan terlihat sangat banyak yang samasumber
Untuk sub-objek,
ReadSubtree()
memberi Anda xml-reader terbatas pada sub-objek, tapi saya benar-benar berpikir bahwa Anda melakukan ini dengan cara yang keras. Kecuali Anda memiliki persyaratan yang sangat spesifik untuk menangani xml yang tidak biasa / tidak dapat diprediksi, gunakanXmlSerializer
(mungkin digabungkan dengansgen.exe
jika Anda benar-benar menginginkannya).XmlReader
adalah ... rumit. Berbeda dengan:sumber
Contoh berikut menavigasi melalui aliran untuk menentukan jenis node saat ini, dan kemudian menggunakan XmlWriter untuk mengeluarkan konten XmlReader.
Contoh berikut menggunakan metode XmlReader untuk membaca konten elemen dan atribut.
sumber
Anda dapat melakukan loop melalui xmlnode dan mendapatkan data ...... C # XML Reader
sumber
Saya tidak berpengalaman. Tapi saya pikir XmlReader tidak diperlukan. Sangat sulit digunakan.
XElement sangat mudah digunakan.
Jika Anda membutuhkan kinerja (lebih cepat), Anda harus mengubah format file dan menggunakan kelas StreamReader dan StreamWriter.
sumber