Golang ile XML Parse Etme

Golang ile ilgili kurulum tarafında herhangi bir probleminiz bulunuyorsa eğer, kurulumla ilgili yayınladığım yazıyı kontrol edebilirsiniz. Bunun yanında Golang’ın eski versiyonu mevutsa, güncel versiyonu yükleme ile ilgili yazımı kontrol edebilirsiniz.

Bu yazımda go ile XML parsing’i anlatacağım. Açıkcası burada iki kısımdan oluşacak; ilk olarak local’de bir XML dosyası oluşturup, onu çekeceğim. ikinci kısımda ise kendi web sitem için oluşturduğum sitemap.xml‘i çekeceğim.

Local’de XML oluşturma ve dosyayı çekme

İlk olarak bir Data adında bir xml dosyası oluşturuyoruz. Aşağıda bu örnek proje için oluşturulan xml içeriği 3 tane kaydımız yer alıyor;

<?xml version="1.0"?>
<data>
   <person>
      <firstname>Yavuz</firstname>
      <lastname>Han</lastname>
      <city>Istanbul</city>
      <districts>Beyoglu</districts>  
   </person>
   <person>
      <firstname>Kadir</firstname>
      <lastname>Kelss</lastname>
       <city>Istanbul</city>
       <districts>Kadıkoy</districts>  
   </person>
    <person>
      <firstname>Şule</firstname>
      <lastname>Belss</lastname>
      <city>Istanbul</city>
      <districts>Atasehir</districts>   
   </person>
</data>     

XML dosyamızı oluşturduktan sonra kodumuzu oluşturmaya başlıyoruz. Burada gerekli kodları parçalar halinde, açıklamarıyla birlikte oluşturacağız. En son olarakta tüm kodları yayınlamış olacağız.

import (
	"encoding/xml"
	"fmt"
	"io/ioutil"
	"os"
)

İlk olarak Go’nun standartında bulunan, XML dosyalarını ayrıştırmada (parse etmede) temel yöntemler sağlayan encoding/xml paketini ekledik. İkinci olarak I/O işlevlerini uygulayan fmt paketini ekledik. Son ikide yer alan paketleri ise dosya işlemlerini halletmek için eklemesi gerçekleştirildi.

type Data struct {
	XMLName    xml.Name `xml:"data"`
	PersonList []Person `xml:"person"`
}

Yukarıda görebileceğiniz üzere XML dosyamızı baz alarak; XML dosyamızdaki <data> değerini tanımladık. İkinci olarak PersonList adında bir değişken tanımladık. Bu tanımlama bize <person>‘u bir dizi olarak verecek.

type Person struct {
	XMLName   xml.Name `xml:"person"`
	Firstname string   `xml:"firstname"`
	Lastname  string   `xml:"lastname"`
	City      string   `xml:"city"`
	Districts string   `xml:"districts"`
}

Yukarıda görebileceğiniz üzere XML dosyamızı baz alarak; xml dosyamızdaki <person></person> altındaki değerleri tanımladık.

func (p Person) String() string {
	return fmt.Sprintf("\t First Name: %s - Last Name: %s - City: %s - Districts: %s  \n", p.Firstname, p.Lastname, p.City, p.Districts)
}

Bu tanımlamaları yaptıktan sonra ekrana yazdıracağımız fonksiyonları yazıyoruz. Daha sonrasında ana fonksiyonumuzu yazdırıyoruz.

func main() {
	xmlFile, err := os.Open("Data.xml")
	if err != nil {
		fmt.Println("Error: ", err)
	}
	defer xmlFile.Close()
   xmlData, _ := ioutil.ReadAll(xmlFile)
   var s Data
	xml.Unmarshal(xmlData, &s)
   fmt.Println(s.PersonList)

Hatırlayacağınız gibi dosya okuma işlemleri için en başta bazı paketleri import etmiştik. Burada ilk olarak Data adındaki XML dosyamızı os ile okuyoruz. Burada dosyamız aynı klasörde olduğu için direkt olarak ekledik. Eğer farklı bir yerde ise PATH yolunu ona göre belirtmek gerekiyor. Sonrasında ise hata kontrolümüzü gerçekleştiriyoruz. Daha sonrasında ise XML dosya açma işlemi bittikten sonra defer ile kapatıyoruz.

Açtığımız dosyadaki verileri xmlData değikenine atadık ve iotil.ReadAll fonksiyonuyla okuduğumuz xmlFile dosyasını veriyoruz. Bir sonraki kısımda ise Data struct’ımızı tanımladık ve unmarshall fonksiyonu ile bunu okuyoruz.

Tüm kod;

package main

import (
	"encoding/xml"
	"fmt"
	"io/ioutil"
	"os"
)

func main() {
	xmlFile, err := os.Open("Data.xml")
	if err != nil {
		fmt.Println("hata: ", err)
	}
	defer xmlFile.Close()

	xmlData, _ := ioutil.ReadAll(xmlFile)

	var s Data
	xml.Unmarshal(xmlData, &s)

	fmt.Println(s.PersonList)
}

type Data struct {
	XMLName    xml.Name `xml:"data"`
	PersonList []Person `xml:"person"`
}

type Person struct {
	XMLName   xml.Name `xml:"person"`
	Firstname string   `xml:"firstname"`
	Lastname  string   `xml:"lastname"`
	City      string   `xml:"city"`
	Districts string   `xml:"districts"`
}

func (p Person) String() string {
	return fmt.Sprintf("\t First Name: %s - Last Name: %s - City: %s - Districts: %s  \n", p.Firstname, p.Lastname, p.City, p.Districts)
}

Terminalde çalıştırdıktan sonra aşağıdaki çıktıyı alıyoruz.

Terminal output

Uzak bir sunucudaki XML’i parse etme

Aşağıda ise kendi sitemdeki sitemap.xml dosyasını parse ettim. İlk örnekten farklı olarak net/http adlı paketi import ettim ve os adlı paketi burada kullanmıyoruz. Aşağıda görüleceği üzere XML dosyasına göre tanımlamalarımı gerçekleştirdim. XML çıktısını incelediğinizde görüleceği üzere, burada sadece loc tagını çekerek bu işlemi gerçekleştirdim.

package main

import (
	"encoding/xml"
	"fmt"
	"io/ioutil"
	"net/http"
)

type UrlSet struct {
	Locations []Location `xml:"url"`
}

type Location struct {
	Loc string `xml:"loc"`
}

func (l Location) String() string {
	return fmt.Sprintf(l.Loc)
}

func main() {
	resp, _ := http.Get("https://manalysiz.com/sitemap.xml")
	bytes, _ := ioutil.ReadAll(resp.Body)
	var s UrlSet
	xml.Unmarshal(bytes, &s)
	fmt.Println(s.Locations)
}