C Sharp Programlama Dili/XML işlemleri
Şimdi isterseniz konu anlatımına başlamadan önce bu derste örnek olarak kullanacağımız XML dosyasını oluşturalım. Dosyaya dosya.xml ismini verelim ve kaynak kod dosyamızla aynı klasöre koyalım:
<?xml version="1.0" encoding="ISO-8859-9" ?>
<öğünler>
<öğün adı="Sabah">
<yiyecek>Peynir</yiyecek>
<içecek>Çay</içecek>
</öğün>
<öğün adı="Akşam">
<yiyecek>Pilav</yiyecek>
<içecek>Ayran</içecek>
</öğün>
</öğünler>
C#'ta XML işlemleri System.XML isim alanındaki sınıflarla yapılır. Konuya başlamadan önce Temel I/O işlemleri konusunu incelemenizde fayda var. Çünkü bu konuda akımlarla içli dışlı olacağız. Akımları unutmuş olabilirsiniz. Bir dosyadaki bilgiler programımıza akımlar aracılığıyla getirilir. Yani dosyadaki tüm veriler bir akım nesnesine atanır. Sonra bu akım üzerinde oynamalar yaparız. Sonra akımı tekrar dosyaya yazıp tamponu boşaltırız. Akımları geçen derste gördüğümüz offline çalışmaya benzetebiliriz.
XmlTextReader sınıfı
değiştirBir XML dosyasından okuma yapmamızı sağlar. Bir XmlTextReader nesnesi şu yollarla oluşturulabilir:
XmlTextReader xtr1=new XmlTextReader("dosya.xml");
XmlTextReader xtr2=new XmlTextReader(Stream akim);
XmlTextReader xtr3=new XmlTextReader(xtr2);
Stream sınıfı System.IO isim alanındadır ve FileStream, NetworkStream vb. sınıfların türediği sınıftır. Yani bir Stream nesnesine Temel I/O işlemleri dersinde gördüğümüz FileStream nesnelerini atayabiliriz. Şimdi XmlTextReader sınıfının üye elemanlarını bir örnek üzerinde görelim:
using System;
using System.Xml;
class xml
{
static void Main()
{
XmlTextReader xtr=new XmlTextReader("dosya.xml");
while(xtr.Read())
if(xtr.NodeType==XmlNodeType.Element)
{
Console.Write("{0,-10}",xtr.Name);
if(xtr.HasAttributes)
{
Console.Write("{0} niteliği var. ",xtr.AttributeCount);
while(xtr.MoveToNextAttribute())
Console.Write("{0}={1}",xtr.Name,xtr.Value);
Console.WriteLine();
}
else
Console.WriteLine("Nitelik yok.");
}
}
}
Bu programın çıktısı şöyledir:
öğünler Nitelik yok. öğün 1 niteliği var. adı=Sabah yiyecek Nitelik yok. içecek Nitelik yok. öğün 1 niteliği var. adı=Akşam yiyecek Nitelik yok. içecek Nitelik yok.
XmlTextReader sınıfına ait olan Read() metodu aktif düğümü bir birim öteler ve true döndürür. Düğüm ötelenemiyorsa false döndürür. Düğüm, bir XML dosyasındaki en küçük birimdir. NodeType özelliği aktif düğümün cinsini XmlNodeType enumu tipinden verir. XmlNodeType enumu System.Xml isim alanındadır. Düğümün tipini Element yaparak yalnızca < ve > karakterleri arasındaki düğümlerin hesaba katılmasını sağladık. Eğer bunu yapmasaydık XML dosyasındaki sonlandırıcılar (</xxx> gibi), yorum satırları (<?xxx?> gibi), salt metinler (< ve > ile çevrelenmeyenler) ve hatta boşluklar da hesaba katılacaktı. Name özelliği aktif düğümün ismini string olarak verir. HasAttributes özelliği eğer ilgili düğümün nitelik (seçenek) kısmı da varsa true, yoksa false döndürür. AttributeCount özelliği ilgili düğümün nitelik sayısını int tipinden döndürür. MoveToNextAttribute() aktif düğümdeki seçenekler arasında öteleme yapar. Başlangıçta herhangi bir seçenek üzerinde olunmaz, düğüm üzerinde olunur. Yani bir seçenek elde edebilmek için en az bir öteleme yapılmalıdır. Öteleyemiyorsa false döndürür. Name ve Value özellikleri aktif seçeneğin ismini ve değerini string olarak döndürür.
NOT: Başlangıçta herhangi bir düğüm üzerinde olunmaz. Bir düğüm elde edebilmek için en az bir öteleme yapılmalıdır.
NOT: Her XML dosyası bir son düğüm içerir.
XmlNodeType enumunun sözcüklerinin tamamı: Attribute, Document, Element, Entity, Notation, Text, CDATA, DocumentFragment, EndElement, EntityReference, ProcessingIntsruction, Whitespace, Comment, DocumentType, EndEntity, None, SignificantWhitespace, XmlDecleration. Bunlardan bizim için önemli olanlar şunlar:
- Attribute → seçenek
- Element → eleman
- Text → salt metin (boşluklar hariç)
- EndElement → her dosyada bulunan son düğüm
- Whitespace → boşluklar
- Comment → yorumlar
- None → Hiçbirisi
NOT: Bütün XML dosyalarının kök düğümü olmalıdır.
NOT: System.Xml isim alanı System.Xml.dll assemblysindedir.
XmlTextReader sınıfının MoveToElement() metodu seçenekler arasında dolaşırken seçeneğin düğümüne geçmek için kullanılır. Örneğin <öğün adı="Sabah"> düğümünde "adı" seçeneğindeysek bu metodu kullanırsak öğün düğümüne geçeriz. Eğer bu metodu bir seçenek üzerindeyken kullanmışsak true döndürür, düğüm üzerindeyken kullanmışsak false döndürür. Doğal olarak bir düğüm üzerinde kullanmışsak herhangi bir şey yapılmaz. Bu metotla Element, DocumentType ve XmlDeclaration düğüm tiplerine geri dönebiliriz. Yine aynı sınıfın MoveToAttribute() metodu ise aktif düğümün seçenekleri arasında dolaşmaya yarar. MoveToNextAttribute() metodunun aksine sadece ileri doğru değil, aktif düğümün istenilen seçeneğine atlama imkanı verir. İki farklı kullanımı vardır:
MoveToAttribute(int i)
MoveToAttribute(string s)
Birincisinde aktif seçenek i. indeksli seçenek yapılırken ikincisinde aktif seçenek ise s isimli (Name) seçenek yapılır. Şimdi bu iki metodu bir örnek üzerinde görelim: (dosya.xml dosyasında <öğün adı="Sabah">
düğümünü <öğün adı="Sabah" saat="8">
olarak değiştirin.)
using System;
using System.Xml;
class xml
{
static void Main()
{
XmlTextReader xtr=new XmlTextReader("dosya.xml");
while(xtr.Read())
if (xtr.AttributeCount>1&&xtr.NodeType==XmlNodeType.Element)
{
Console.Write(xtr.Name+" düğümünün seçenekleri: ");
for (int i = 0; i < xtr.AttributeCount; i++)
{
xtr.MoveToAttribute(i);
Console.Write("{0}={1} ", xtr.Name, xtr.Value);
}
xtr.MoveToElement(); //son tahlilde düğüm aktif hâle getirildi.
}
}
}
XmlTextWriter sınıfı
değiştirXmlTextWriter sınıfı programlama yoluyla XML dosyaları oluşturmak amacıyla kullanılabilir. Örnek program:
using System.Xml;
class Xtw
{
static void Main()
{
XmlTextWriter xtw=new XmlTextWriter("yeni.xml",System.Text.Encoding.GetEncoding("windows-1254"));
xtw.Formatting=Formatting.Indented;
xtw.WriteStartDocument(); //XML belgesine versiyon bilgisi yazılıyor.
xtw.WriteComment("Bu bir denemedir");
xtw.WriteStartElement("üst_düğüm");
xtw.WriteStartElement("alt_düğüm");
xtw.WriteAttributeString("seçenek","değer");
xtw.WriteString("Salt yazı");
xtw.WriteEndElement();
xtw.WriteEndElement();
xtw.WriteEndDocument();
xtw.Close();
}
}
Bu programın ürettiği XML dosyası şöyle olacaktır.
<?xml version="1.0" encoding="windows-1254"?>
<!--Bu bir denemedir-->
<üst_düğüm>
<alt_düğüm seçenek="değer">Salt yazı</alt_düğüm>
</üst_düğüm>
Metotları açıklama gereksinimi görmüyorum. Hepsi yeterince açık. XmlTextWriter nesneleri farklı yollarla oluşturulabilir:
XmlTextWriter xtw1=XmlTextWriter(string dosya,System.Text.Encoding kodlama); //örneğimizdeki gibi
XmlTextWriter xtw2=XmlTextWriter(Stream akim,System.Text.Encoding kodlama);
XmlTextWriter xtw3=XmlTextWriter(TextWriter xw); //TextWriter sınıfı System.IO isim alanındadır.
XmlDocument, XmlAttribute, XmlElement ve XmlNode sınıfları
değiştirBu sınıflar özetle XmlTextReader ve XmlTextWriter sınıflarının yaptığı işleri yaparlar ancak daha gelişmiş özellikler sunar. XmlDocument bir XML dosyasını, XmlAttribute bir düğümün seçeneklerini, XmlElement bir dosyadaki element düğümleri ve XmlNode düğümleri temsil eder.
XmlDocument sınıfı
değiştirBir XmlDocument nesnesi şöyle oluşturulabilir:
XmlTextReader xtr=new XmlTextReader("dosya.xml");
XmlDocument xd=new XmlDocument();
xd.Load(xtr);
XmlNode sınıfı
değiştirBir XmlNode nesnesi şöyle oluşturulabilir:
XmlTextReader xtr=new XmlTextReader("dosya.xml");
XmlDocument xd=new XmlDocument();
xd.Load(xtr);
XmlNodeList xnl=xd.ChildNodes;
XmlNode xn=xnl[0];
XmlNode sınıfının önemli özellikleri şunlardır: (tamamı static değildir)
XmlAttributeCollection Attributes İlgili düğümün seçeneklerini bir XmlAttributeCollection nesnesi olarak döndürür. Bu koleksiyon XmlAttribute nesnelerinden oluşur. (salt okunur)
XmlNode ParentNode Üst düğümü XmlNode tipinden döndürür. (salt okunur)
bool HasChildNodes İlgili düğüm alt düğüm(ler) içeriyorsa true, içermiyorsa false döndürür. (salt okunur)
XmlNode FirstChild İlgili düğümün ilk alt düğümünü döndürür. (salt okunur)
XmlNode LastChild İlgili düğümün son alt düğümünü döndürür. (salt okunur)
XmlNodeList ChildNodes İlgili düğümün alt düğümlerini XmlNodeList tipinden döndürür. (salt okunur)
XmlNode NextSibling Aktif düğümden hemen sonraki düğümü döndürür. (salt okunur)
XmlNode PreviousSibling Aktif düğümden bir önceki düğümü döndürür. (salt okunur)
string InnerText Aktif düğümün yazısını -varsa- alt düğümlerin yazılarıyla birlikte yan yana ekleyerek döndürür. <düğüm>Yazı</düğüm>
ifadesinde düğüm düğümünün yazısı "Yazı"dır.
string InnerXml Aktif düğümün içindeki her şeyi, XML etiketleri de dâhil olmak üzere döndürür.
string OuterXml Az öncekinden tek farkı düğümün kendi XML etiketlerini de döndürmesidir. (salt okunur)
string Name Düğümün ismi. (salt okunur)
string Value İlgili düğüme ilişkin değer. Tuttuğu değer düğüm tipine göre değişir. Örneğin düğüm tipi yorumsa yorumun içindeki yazı döndürülür, düğüm tipi elementse null döndürür.
XmlNodeType NodeType Düğümün tipini XmlNodeType enumu cinsinden verir. (salt okunur)
XmlElement sınıfı
değiştirXmlNode sınıfından türemiştir. Dolayısıyla bu sınıftaki tüm üye elemanları içerir. Bir XmlElement nesnesi şöyle oluşturulabilir:
XmlTextReader xtr=new XmlTextReader("dosya.xml");
XmlDocument xd=new XmlDocument();
xd.Load(xr);
XmlElement xe=xd.DocumentElement; //xe -> ilk element
Son olarak XmlDocument sınıfının Save() metodu ilgili XmlDocument nesnesinde yapılan değişikliklerin dosyaya geri yazılmasını sağlar:
using System;
using System.Xml;
class xml
{
static void Main()
{
XmlTextReader xtr=new XmlTextReader("dosya.xml");
XmlDocument xd=new XmlDocument();
xd.Load(xtr);
XmlNodeList xnl=xd.ChildNodes;
xnl[1].ChildNodes[0].ChildNodes[0].InnerText="Domates";
xd.Save("dosya2.xml");
}
}
Eğer bu programda Save() metodunun parametresine dosya.xml yazsaydık sistem hata verecekti. Çünkü dosyayı aynı anda hem XmlTextReader sınıfı hem de XmlDocument sınıfı kullanıyordu. Bu sorunu aşmak için programı şöyle yazabiliriz:
using System;
using System.Xml;
class xml
{
static void Main()
{
XmlTextReader xtr=new XmlTextReader("dosya.xml");
XmlDocument xd=new XmlDocument();
xd.Load(xtr);
XmlNodeList xnl=xd.ChildNodes;
xnl[1].ChildNodes[0].ChildNodes[0].InnerText="Domates";
xtr.Close();
xd.Save("dosya.xml");
}
}
Burada öncelikle xtr nesnesinin tuttuğu dosyayı bırakmasını sağladık. Sonra serbest kalan dosyaya yazma işini başarıyla gerçekleştirdik.