Makale Özeti

Verileri XML'de saklanan bir adres defterinin nasıl yapılabileceğini inceleyip. XML konusunda ve Xpath ile sorgulamalar konusunda örnekler.

Makale

Merhabalar,

XML(Extensible Markup Language) bir markup dilidir.Markup dillerine örnek olrak HTML,WML vs.. verilebilir. Bu dillerde veriler bazı işaretlerle (etiket) işaretlenirler. Örneğin bir HTML kodunda bir başlık yazısı <h1> etiketi ile işaretlenir. Sonuç olarak bir belgedeki verileri işaretlemeye yarayan dillere markup dilleri denir.

Bağımsız bir kuruluş olan W3C (World Wide Web Consortium) organizasyonu tarafından tasarlanan ve herhangi bir kurumun tekelinde bulunmayan XML (eXtensible Markup Language), kişilerin kendi sistemlerini oluşturabilecekleri, kendi etiketlerini tanımlayarak çok daha rahat ve etkin programlama yapabilecekleri ve bu belirlenen etiketleri kendi yapıları içerisinde standardize edebilecekleri esnek, genişleyebilir ve kolay uygulanabilir bir meta dildir.

Çok farklı tipteki verileri orjinal formatlarında tek bir havuzda tutabilen XML, bilgiye hızlı, kolay ve ortamdan bağımsız olarak erişebilme imkanı sunar. Günlük yaşantımızda kullanmakta olduğumuz verilerin %80’ini oluşturan ve “unstructured” olma özellikleri nedeniyle kendi bulundukları medya dışında veri özelliklerini koruyamayan (kelimeişlem, elektronik tablo çıktıları, PDF dokümanları, ses,resim vb) farklı tipteki verilerin, oryantasyona gerek duymadan hiyerarşik bir yapıda kullanılabilmelerine olanak vermekte ve bu verilerin hızlı bir şekilde sorgulanabilmelerini sağlamaktadır. Öncelikle veri transferinin kolaylaşmasını ve verinin içerik bilgisiyle saklanabilmesini hedefleyen XML, içerik ve sunum bilgilerini birbirinden ayırır. Bu özelliği ile de HTML'den farklılaşır

XML in diğer bir özelliği ise farklı platformlar arasında veri taşınabilmesine imkan sunmasıdır.

Örnek olarak bir adres defteri yapıp inceleyecegiz. Uygulamamıza system.xml namespaceini import edeceğiz. Yarattıgımız XML dosyamız

   <?xml version="1.0" encoding="utf-8"?>
   <myAddresses>
      <myAdress>
         <name>Adım</name>
         <surname>Soyadım</surname>
         <address>Adresim</address>
         <phone>Telefonum</phone>
      </myAdress>
   </myAddresses>
Şeklinde olacaktır.Adres defterimizdeki her kayıt <myAddresses> düğümünün içinde bulunacak ve bu kayıda ait alt bilgiler ise alt düğümlerde yer alacaktır. Bu xml dosyası uygulamamızda aynı klasörde ve adress.xml ismindedir.

   Sub GetAddresses()
      Dim ds As New DataSet
      ds.ReadXml("adress.xml")
      If ds.Tables.Count > 0 Then
         dgAdres.DataSource = ds.Tables(0)
         Dim doc As New XmlDocument
         doc.Load("adress.xml")
         Dim currentNode As XmlNode
         currentNode = doc.DocumentElement
         Label1.Text = "Toplam " & currentNode.ChildNodes.Count.ToString & " adet kayıt bulundu."
      Else
         Label1.Text = "Kayıt Bulunamadı
      End If
   End Sub

Uygulamamızda bu XML dosyasının verilerini datasete aktarmak için datasetin ReadXml() metodunu kullanabiliriz.ReadXml metodu ile xml dosyanın yapısını tamamen içeren bir dataset oluşacaktır. Ve biz bu dataseti i datagrid in source u olarak gösterirsek verileri datagridimize doldurabiliriz. Yukarıda bulunan sub bu işlemi yapmaktadır, ancak xml dosyada veri bulunmuyorsa dataset in içindeki tablo dolmayacağından tablo oluşmayacaktır. Bundan dolayı tablo oluşmuyorsa belirlediğimiz bir label da kayıt yok yazısını yazdırmamız uygun olacaktır.Kaç kayıt döndüğünü saymak için ise root elementimizin altındaki child node ların sayısını alabiliriz.

   Private Sub btnDelete_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDelete.Click
      Dim doc As New XmlDocument
      doc.Load("adress.xml")
      Dim node As XmlNode
      Dim currentNode As XmlNode
      currentNode = doc.DocumentElement
      node = currentNode.SelectSingleNode("//myAdress[name='" & dgAdres.Item(dgAdres.CurrentRowIndex, 0).ToString & "'][surname='" & dgAdres.Item(dgAdres.CurrentRowIndex, 1).ToString & "'][address='" & dgAdres.Item(dgAdres.CurrentRowIndex, 2).ToString & "'][phone='" & dgAdres.Item(dgAdres.CurrentRowIndex, 3).ToString & "']")
      currentNode.RemoveChild(node)
      doc.Save("adress.xml")
   End Sub
Seçili bir kayıdı silmek için yazdığımız bu sub da ise ilk önce bir tane xmlDocument tanımlayarak ve load metodunu kullanarak xml dosyamızı programımızda açıyoruz.Current node değişkenine root elementimizi atıyoruz. Ve root elementimizin altından selectsinglenode kullanarak tek bir düğümü geri döndürecek şekilde bir sorgulama yaptırıyoruz.Bu sorgulamada datagridde bulunan her bir hücredeki veriyi barındıran benzersiz olması gereken düğümü geriye döndürüyoruz ve bulundugumuz düğümün removechild metodunu kullanarak sorgulama sonucu elde ettiğimiz düğümü kaldırıyoruz. Burada unutulmaması gereken xml dosyayı programımızda açıp değişiklik yaptıktan sonra mutlaka save metodunu kullanarak kaydetmemizdir.

   Private Sub btnSearch_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSearch.Click
      Dim xmlnodename As String
      Select Case cbCriteria.SelectedItem.ToString
         Case "Ad"
            xmlnodename = "name"
         Case "Soyad"
            xmlnodename = "surname"
         Case "Adres"
            xmlnodename = "address"
         Case "Telefon"
            xmlnodename = "phone"
      End Select
      Dim doc As New XmlDocument
      doc.Load("adress.xml")
      Dim currentNode As XmlNode
      currentNode = doc.DocumentElement
      Dim results As XmlNodeList
      If CheckBox1.Checked Then
         results = currentNode.SelectNodes("//myAdress[contains(" & xmlnodename & ",'" & txtSearch.Text & "')]")
      Else
         results = currentNode.SelectNodes("//myAdress[" & xmlnodename & "='" & txtSearch.Text & "']")
      End If
      Dim x As Integer
      Dim ds As DataSet = New DataSet
      Dim xReader As XmlTextReader
      For x = 0 To results.Count - 1
         xReader = New XmlTextReader(results.Item(x).OuterXml, XmlNodeType.Element, New XmlParserContext(Nothing, Nothing, Nothing, XmlSpace.None))
         ds.ReadXml(xReader, XmlReadMode.InferSchema)
      Next x
      If ds.Tables.Count > 0 Then
         dgAdres.DataSource = ds.Tables(0)
         Label1.Text = "Toplam " & ds.Tables(0).Rows.Count & " adet kay? bulundu."
      Else
         dgAdres.DataSource = Nothing
         Label1.Text = "Kay? Bulunamad?
      End If
   End Sub
Xml dosya içinde arama yapmak için ise silmede yaptığımız gibi xml document i açarak içinden uygun kriterlere göre düğümlerden oluşan bir nodelist döndürmek. Ancak burada sorgulama bire bir eşleşen kayıtları bulmak için = kullanarak içinde geçen kelimeye göre kayıt bulmak için xpath komutlarından contains i kullanarak olmaktadır. Fakat şimdi oluşturduğumuz bu xml dosyadaki düğüm listesini dataset e aktarmak için xmltextreader kullanarak geçici bir xml dosya yapısı elde ediyoruz. ve bunu dataset e aktarıyoruz.

   Sub AddAddress()
       Dim doc As New XmlDocument
       doc.Load("adress.xml")
       Dim NewMyAdress As XmlNode = doc.CreateElement("myAdress")
       Dim newName As XmlNode = doc.CreateElement("name")
       Dim newSurname As XmlNode = doc.CreateElement("surname")
       Dim newAddress As XmlNode = doc.CreateElement("address")
       Dim newPhone As XmlNode = doc.CreateElement("phone")
       Dim NewnameText As XmlNode = doc.CreateTextNode(txtName.Text)
       Dim NewsurnameText As XmlNode = doc.CreateTextNode(txtSurname.Text)
       Dim NewaddressText As XmlNode = doc.CreateTextNode(txtAddress.Text)
       Dim NewphoneText As XmlNode = doc.CreateTextNode(txtPhone.Text)
       NewMyAdress.AppendChild(newName)
       newName.AppendChild(NewnameText)
       NewMyAdress.AppendChild(newSurname)
       newSurname.AppendChild(NewsurnameText)
       NewMyAdress.AppendChild(newAddress)
       newAddress.AppendChild(NewaddressText)
       NewMyAdress.AppendChild(newPhone)
       newPhone.AppendChild(NewphoneText)
       Dim targetnode As XmlNode
       targetnode = doc.SelectSingleNode("//myAddresses")
       targetnode.AppendChild(NewMyAdress)
       doc.Save("adress.xml")
   End Sub

XML dosyada kayıt eklemeler root element içine yapılacağından her node tek tek yaratılır. ve en alttaki node içine yazılması gereken değerler de yaratıldıktan sonra nodelar hiyerarşik yapılarına göre birbirlerine appendChild metodu kullanılarak bağlanır. ve birbirlerinin altında yer almaları sağlanarak bir tek node altında kayıtlar oluşturulur. Bu kayıdı taşıyan node ise root elemente append child ile eklenerek döküman kaydedilir ve xml dosyaya veri ekleme işi bitirilir.

   Sub getUpdateInformation()
       For Each xe As XmlElement In Guncellemi
       If xe.Name = "name" Then
       txtName.Text = xe.InnerText
       ElseIf xe.Name = "surname" Then
       txtSurname.Text = xe.InnerText
       ElseIf xe.Name = "address" Then
       txtAddress.Text = xe.InnerText
       ElseIf xe.Name = "phone" Then
       txtPhone.Text = xe.InnerText
       End If
       Next
   End Sub
Güncelleme yapmak için ilk önce seçili kayıdın bilgilerine ulaşmak gerekir buda yukarıda incelendiği gibi basit bir sorgu sonucu oluşan node ın içindeki değerlerin okunması ile elde edilir.

   Private Sub btnUpdate_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnUpdate.Click
       Dim doc As New XmlDocument
       doc.Load("adress.xml")
       Dim currentNode As XmlNode
       currentNode = doc.DocumentElement
       Guncellemi = currentNode.SelectSingleNode("//myAdress[name='" & dgAdres.Item(dgAdres.CurrentRowIndex, 0).ToString & "'][surname='" & dgAdres.Item(dgAdres.CurrentRowIndex, 1).ToString & "'][address='" & dgAdres.Item(dgAdres.CurrentRowIndex, 2).ToString & "'][phone='" & dgAdres.Item(dgAdres.CurrentRowIndex, 3).ToString & "']")
       Dim cust As XmlNode
       Dim newNode As XmlNode
       Dim NewMyAdress As XmlNode = doc.CreateElement("myAdress")
       Dim newName As XmlNode = doc.CreateElement("name")
       Dim newSurname As XmlNode = doc.CreateElement("surname")
       Dim newAddress As XmlNode = doc.CreateElement("address")
       Dim newPhone As XmlNode = doc.CreateElement("phone")
       Dim NewnameText As XmlNode = doc.CreateTextNode(txtName.Text)
       Dim NewsurnameText As XmlNode = doc.CreateTextNode(txtSurname.Text)
       Dim NewaddressText As XmlNode = doc.CreateTextNode(txtAddress.Text)
       Dim NewphoneText As XmlNode = doc.CreateTextNode(txtPhone.Text)
       NewMyAdress.AppendChild(newName)
       newName.AppendChild(NewnameText)
       NewMyAdress.AppendChild(newSurname)
       newSurname.AppendChild(NewsurnameText)
       NewMyAdress.AppendChild(newAddress)
       newAddress.AppendChild(NewaddressText)
       NewMyAdress.AppendChild(newPhone)
       newPhone.AppendChild(NewphoneText)
       Dim oldNode As XmlNode
       Dim targetnode As XmlNode
       targetnode = doc.SelectSingleNode("//myAddresses")
       For Each nd As XmlNode In targetnode.ChildNodes
       If nd.InnerText = Guncellemi.InnerText Then
           oldNode = nd
       End If
       Next
       cust = currentNode.ReplaceChild(NewMyAdress, oldNode)
       doc.Save("adress.xml")
       Me.Close()
   End Sub

Update işlemi için ilk önce seçtiğimiz kayıda ait verileri bulunduran düğümü seçiyoruz. Daha sonra ise verilerin yeni hallerini barındıran düğümü aynı yeni kayıt ekleme işleminde olduğu gibi oluşturuyoruz ve replaceChild metodunu kullanarak eski düğümü yeni düğümle değiştirip dosyamızı kaydediyoruz.

   Private Sub btnExport_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExport.Click
      Dim doc As New XmlDocument
      doc.Load("adress.xml")
      Dim currentNode As XmlNode
      Dim str As String
      currentNode = doc.DocumentElement
      For Each x1 As XmlNode In currentNode
         For Each x2 As XmlNode In x1
            str &= x2.InnerText & ","
         Next
         str = str.Substring(0, str.Length - 1)
         str &= vbNewLine
      Next
      SaveFileDialog1.ShowDialog()
      Dim strwriter As New StreamWriter(SaveFileDialog1.FileName)
      strwriter.Write(str)
      strwriter.Close()
   End Sub
Verileri dışarıyla ortak bir dosya olan csv yani Comma Separated Value (Virgülle ayrılmış değerler) olarak kaydediyoruz. Bunun için root element içindeki düğümlerde tek tek dolaşıp değerlerini alarak "," lerle ayırarak yeni bir text dosyası oluşturuyoruz.

Bu makalemizde sizlerle xml kullanarak ve sorgulayarak çok basit bir adres defteri yazdık bu adres defterine ait kodlara buradan ulaşabilirsiniz. Bu çalışma makaleye örnek teşkil ettiği ve öğrenme amaçlı olduğundan hata testleri ve hata yakalama fonksiyonları yazılmamıştır.

oztamer@hotmail.com
tamer.oz@yazgelistir.com
oztamer@hotmail.com
Ornek Kodlar