Makale Özeti

Bu makale serisinde; System.Xml 2.0 ile gelen bazı yeni özelliklere bakacağız ve sıklıkla kullandığınız bazı XML programlama işlerinizi, yeniliklerle birlikte nasıl daha kolay hale getirebileceğinizi göreceğiz. Serinin bu makalesinde, gelen yeniliklere bir giriş ile birlikte XML verilerini okuma işi üzerinde yoğunlaşacağız.

Makale

System.Xml 2.0 İle Gelen Yenilikler I

İlk XML kodu yazdığım günleri hatırlıyorumda, ne kadar heyecan vericiydi. ASP ile birlikte verileri sorunsuzca bir yerden bir yere hızlı bir şekilde taşıyabiliyorduk. Şimdi gelinen noktaya bir bakın. Microsoft® .NET Framework 2.0 içeren beta dvd ler daha avuçlarımıza düşer düşmez, hemen incelemeye koyulmuş ve inceledikçe de hayran kalmıştık. O hayranlık verecek gelişmelerden birisi de tüm .NET tabanlı web service uygulamalarının kalbi olan System.XML içinde gerçekleşti.

Evet şimdi makaleye girişimizden de anlaşıldığı gibi, bu makale de System.Xml 2.0 ile gelen bazı yeni özelliklere bakacağız ve sıklıkla kullandığınız bazı XML programlama işlerinizi yeniliklerle birlikte nasıl daha kolay hale getirebileceğinizi göreceğiz.

System.Xml 2.0 İle Birlikte Neler Hedeflendi?

Aslında System.Xml performansının geliştirilmesinin nedenini, System.Xml 2.0 içinde gelen birçok değişikliğe baktığımızda görebiliriz. System.XML 2.0 ı geliştiren ekip, oldukça başarılı ve önemli kaynaklara imza attı. Örneğin, .NET Framework 1.1 içinde gelenler ile karşılaştırdığımızda; yeni XmlTextReader ve XmlTextWriter sınıfları öncekilerine göre iki kat daha hızlı hale geldi, XSLT performansı dörtte üçü oranında arttı ve XML şema doğrulaması artık %25 daha hızlı.

Gerçekten bu şekilde performans arttıran gelişmelerin sağlanabilmesi için, önemli bir optimizasyon ve yeniden tasarım gerekliydi. Örneğin, NET XSLT uygulamasını, yerini aldığı eski MSXML 4.0 dan daha hızlı yapmak için ciddi bir çalışma gerekiyordu. Şimdi System.Xml 2.0 da, XSLT uygulaması direkt olarak runtime da derlenen ve makina kodu olarak çalıştırılan Microsoft Intermediate Language (MSIL) u oluşturuyor. Sonuç olarak da aslında birçok noktada MSXML 4.0 ile aynı performansı gösteriyor.

Eğer gerçekten bu yenilikler ile birlikte bir adım öne çıkmak istiyorsak; bu yeni ve geliştirilmiş System.Xml kütüphanesini, en doğru şekilde kullanabilmemiz gerekir. Ki bunların bir çoğunu ben size anlatacağım :) Bu arada performansa ek olarak, diğer tasarım hedefleri de; geliştirilmiş kullanılabilirliği, uyumluluğu ve standartları içeriyordu. System.Xml 2.0 ın geliştirilme sürecinin sonuna bakıldığında, System.Xml takımının pazar için en uygun ve pratik çözümleri nasıl dikkatle sunduklarını açık bir şekilde görebiliriz.

Şimdi, biraz da çeşitli XML programlama işlerine bakalım ve bu yeni ve geliştirilmiş kütüphaneyi kullanarak; onlarla nasıl baş edeceğimizi öğrenelim.

XML Okuma

Mümkün olduğunca hızlı ve etkili bir şekilde XML okumak istediğinizde, XmlReader kullanabilirsiniz. XmlReader soyut bir sınıfdır ve XmlTextReader, XmlValidatingReader ve kütüphane tarafından içinde kullanılan birkaç türetilmiş sınıf içerir.

2.0 sürümünde gelen en önemli değişikliklerden biri XmlReader nesnelerini nasıl yaratabildiğimiz ile ilgilidir. Yeni statik Create methodunu kullanarak; XmlReader ı yaratabiliriz. Takip eden kodda, Siparis.XML dosyasını okuyabilmek için XmlReader ı nasıl yaratacağınızı görebilirsiniz.

Bu kod varsayılan konfigurasyonu kullanarak XmlReader ı yaratır. Create i çağırırken, XmlReaderSettings nesnesini ekleyerek; XmlReader ı konfigüre edebilirsiniz. Aşağıdaki örnekte de nasıl ayarlar yapabileceğinizi görebilirsiniz. Örneğin burada, beyaz alanlar yorumlar, DTD (Document Type Definition) vs. iptal ediliyor.

Bu pattern ın sağladığı en büyük faydalardan biri sizi konfigurasyon detaylarından koruması. Şimdi, basitçe diğerlerini bir kenara koyup, XmlReaderSettings sınıfı ve Create metodu üzerinde yoğunlaşalım.

Ek olarak bu pattern, güçlü özelleştirilmiş iç optimizasyonlar yapmanıza izin verir. Bu optimizasyonlar daha öncede bahsettiğimiz performans artışları sağlar. Bu koruma, , XmlReader arayüzü aynı kaldığı müddetçe client ları etkilemeden yeni optimizasyonlarla kütüphanenin gelişmesine izin verir. İsterseniz yine direkt olarak sadece XmlReader alt sınıfları ile çalışabilirsiniz ama bu özelliklerin hepsinin avantajlarından yararlanamamış olursunuz.

Kullanımdaki XmlReader uygulamalarını doğru bir şekilde kapatma da oldukça önemlidir. Version 1.1 de, uygun anda Close u çağırmak gerekirdi. System.Xml 2.0 da ise, XmlReader tabanlı sınıflar aşağıdaki kodun kullanımına izin veren IDisposable ı uygular.

Kullanılan kodun sonunda Dispose çağrıldığında, Dispose, XmlReader nesnesindeki Close u çağırır.

Değerleri Dönüştürme

Şu ana kadar bahsettiğim gelişmelere ek olarak, version 2.0 XML metinlerini .NET değerlerine çevirme işlemini de kolaylaştırıyor. Şimdi aşağıdaki Siparis.XML dosyasına bir bakalım ve bu yeni özellikleri kullanarak neler yapabiliriz bir görelim.

Siparis.XML Dosyası
 

Şimdi şöyle bir senaryo oluşturalım. Görevimiz her bir < Fiyat > elementinin içeriğini; System.Double değeri ile okumak olsun. .NET Framework 1.1 de, < Fiyat > içeriğini önce string olarak okur daha sonra da XmlConvert sınıfını kullanarak string değerini System.Double değerine çevirirdik. Fakat bunu XML uygulamalarında ne kadar sıklıkla kullandığımızı düşündüğümüzde, tek tek bu işlemleri yapmak gerçekten can sıkıcı olur. İşte System.XML 2.0 da tüm bu işlemleri otomatik olarka gerçekleştiren methotlar vardır.

İki tip dönüşüm metodu vardır. ReadContentAsXXX ve ReadElementContentAsXXX den birisini seçerek kullanabilirsiniz. Kursör, metin ya da özellik düğümünde konuşlandığında, ReadContentAsXXX i kullanabilirsiniz. Yine kursör, başlangıç element düğümüne konuşlandığında ve onun içeriğini okumak isteyip; kursörü de son element düğümünün sonuna taşımak istediğinizde de ReadElementContentAsXXX i kullanabilirsiniz.

Aşağıda ReadElementContentAsDouble kullanılarak hazırlanmış olan bir örneği görebilirsiniz.

.NET Framework 2.0, .NET tiplerini dinamik olarak belirlemenize imkan sağlayan jenerik ReadContentAs ve ReadElementContentAs metotlarını da getirir. Boşlukla sınırlı bir listeyi .NET dizisi içinde oluşturmak; bu metotları kullanma nedenlerinizden biridir. Örneğin, aşağıdaki bir kaç fiyat bilgisi içeren < Fiyat > elementini düşünün.

Bu fiyat elementini aşağıda yazıldığı gibi, tip olarak double[] ı seçerek okuyabilirsiniz.

Fiyat Bilgisini Double Dizisine Çeviren Kod
 

Büyük Değerleri Okuma

XmlReader, büyük miktardaki verileri daha etkili okuyabilmek için bir dizi yeni methot takımına sahiptir. ReadValueChunk büyük miktardaki karakter grubunu bir seferde okumanıza olanak sağlar. ReadContentAsBase64 ya da ReadContentAsBinHex i, Base64 ya da BinHex kodlarından büyük metin gruplarını elde etmeniz gerektiği zamanlarda kullanabilirsiniz. System.Xml takımı yine bu işin tam tersini gerçekleştirebilmemiz için ReadElementContentAsBase64 ve ReadElementContentAsBinHex türevlerini geliştirmiştir.

Düğümleri Bulma

Dönüştürme ile ilgili geliştirmelere ek olarak, System.Xml 2.0 doküman içindeki istenilen düğümleri bulabilmeyi kolaylaştımak için ReadToDescendant, ReadToFollowing, ve ReadToSibling gibi birkaç methot sağlar. Bu metotlat belirli bir eksen boyunca düğüm sıraları içinde arama yapabilir. Örneğin, daha önceden verdiğim Siparis.Xml içindeki < Fiyat > elementini soyunu bulmamız gerekirse, ReadToDescendant kullanabiliriz. Yine aynı şekilde < Fiyat > elementinin doküman içinde o anki düğümden hemen sonra nereyi geldiğini bulmak içinde; ReadToFollowing kullanabiliriz. Son olarak da, bir sonraki kardeş düğümü bulmamız gerekirse, ReadToNextSibling kullanabiliriz. Bu metotların her biri genel veri okuma senaryoların hepsi için çok kullanışlıdır. Aşağıdaki kod ile bu metotları kullarak; Siparis.Xml dosyası için toplam siparis tutarını hesaplayarak, yazdırıyoruz.

Siparis Toplamını Hesaplayan ve Yazan Kod
 

Aynı işi .NET Framework ün 1.1 versiyonu kullanarak yapmaya kalksaydık, kursör yönetimi ve tip dönüşümleri için daha fazla kod yazacak, solution ı şişirecek, karmaşıklaştıracak ve daha fazla hata için zemin hazırlayacaktık. Bu birkaç metot ise, kodun kolayca okunmasını ve sürekliliğini koruyarak; büyük verimlilik sağlıyor.

Alt Ağaçları Okuma

Kursör yönetiminin oldukça zor olan bir başka yönü ise, XmlReader referansı üzerinden geçirilen bir metot ile istenilen alt ağaca ulaşabilme işlemidir. Bu metot çok fazla dikkat gerektiren bir işlemdir. Metodun alt ağacı ulaşabilme işlemini bitirdiğinde; ne zaman hangi kodu çağıracağı ve XmlReader nesnesinden ayrılacağı düzgün tanımlanmalıdır. Örneğin aşağıdaki metotun XmlReaders nesnesini girdi (burada görev < Adresler > elementinin alt ağaçlarına ulaşabilme olsun) olarak aldığını varsayalım.

Bu gerçekten de uygun bir uygulama değil. İşlemin sonuna ulaşana kadar gereksizce Read i çağırarak; kursörün < Adresler > düğümünün sonuna kadar ilerlemesine neden olur. Buradaki doğru uygulama ise direkt olarak < Adresler > düğümünün sonunu belirleyebilmek ve orada durabilmektir.

İşte System.XML 2.0 içinde, ReadSubtree metodu bu tip senaryolara çözüm için geliştirilmiştir. Peki ne yapar bu metot? Bu metot, çağrıldığı zaman, o anki düğümün sonunu okuyacak farklı bir XmlReader nesnesi yaratır ve o düğümün üzerine kursörü konuşlandırır. Örneğin aşağıdaki snippet da, < Adresler > alt düğümü için XmlReader ı nasıl kullanabileceğimizi görebiliriz.



Bu makalede; System.Xml 2.0 ın, XmlReader kullanarak XML dokümanlarını okuyabilmek için birçok yenilik sağladığını ve geliştirilen birçok yeni metodun işlerimizi nasıl kolaylaştırdığını ve güvenli bir şekilde hızlandırdığını gördük. İki seriden oluşan bu dizinin ikinci makalesinde ise, daha çok XML in yazma, doğrulama, yükleme, kaydetme gibi işlemler üzerinde yoğunlaşarak yeniliklerin getirdiği kolaylıklara hep birlikte bakacağız.

Bir sonraki makalelerde görüşmek üzere. İyi çalışmalar...


Tayfun AKCAY

tayfun@tayfunakcay.com