Aklımda Kalası Kelimeler

* давайте работать вместе
* Zarf ve Mazruf, Zerafet(xHoyratlık) ile aynı kökten(za-ra-fe) gelir
* Bedesten
* Suç subuta ermiştir - Suç sabit olmuştur
SAXException etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
SAXException etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

24 Temmuz 2011 Pazar

Java'da DefaultHandler

Referanslar:
oracle.com
jenkov.com
java2s.com
ibm.com
godoro.com
www.ahmetcebisli.net
Kısaltmalar:

SAX : Simple API for XML
DOM : Document Object Model
XML : Extensible Markup Language

PARSER : ÇÖZÜMLEYİCİ
Java'da XML Çözümleyiciler: Sax Parser, Dom Parser, Xml Pull Parser


Öncelikle bu çözümleyicilerin avantaj ve dezavantajları:
  • SAX çözümleyici, DOM çözümleyiciden hızlıdır, az belek harcar. Söylenti odur ki; DOM çözümlemede SAX kullanır ve üstüne ek işleri yapar. Nitekim DOM veriyi bir kere belleğe yüklerken, akış(stream) temelli olan SAX işini gördükten sonra bellkele ilişkisini keser. Oysa DOM tüm düğümleri(xml etiketlerini) bağladıktan sonra işleme müsade eder.




Aşağıdaki örneği jenkov.com dan aldım aslında ama referanslardaki diğer örneklerle birleştirerek anladığımı not olarak yazayım istedim.
DefaultHandler hakkında biraz fikir veriyor ;)

Özetle: DefaultHandler

Aşağıdaki xml'i SAXParser'a göndereceğiz. XML'i veritabanındaki bir tablo gibi düşünün. Tablonun satırlarıda var tabii. Her satırını XML etiketlerine sardığınızı düşünün. Bu XML etiketleri içlerinde tablonun satırındaki her kolonunu ayrı XML etiketlerine sarılmış olarak düşünün. İşte aşağıdaki XML bizim tablomuz, her child etiketi satırlarımız ve grandchild etiketlerininde sütunumuz olduğunu düşünün. Düşündünüz mü? E o zaman XML'in neden veri taşımada çok becerikli ortacımız olduğunu anlamışsınız. Şimdi biz aşağıdaki XML'i bir sınıf gibi düşünün. child adında bir sınıfımız var. grandchild adında String veri tutan birde property'si, field'ı ya da global değişkeni olsun(hepsinin aslında neredeyse aynı anlamları olduğunu biliyorsunuz zaten). Şimdi biz bu child sınıfından her satır veri için birer nesne türeteceğiz. Bu işi yapmak için SAXParser kardeşimizin bu satırı parçalamak istediğimiz şablonu istemesi çok normal. İşte bu şablonu DefaultHandler sınıfını miras alarak yapacağız.

ornek.xml
<root>
    <child>
        <grandchild>text 1</grandchild>
    </child>
    <child>
        <grandchild>text 2</grandchild>
    </child>
</root>


// Sonucu görmek için çalışacak sınıfımız.
// Giriş noktası ya da metodu olan projenin tek sınıfı.
// (entry point: static void main() metodu yani sınıfın çalıştırılacak ilk metodu) olan tek sınıfımız)
public class MainClass {
  public static void main(String args[])throws Exception {
    SAXParserFactory spf = SAXParserFactory.newInstance();
    SAXParser parser = spf.newSAXParser();

    MySAXHandler handler = new MySAXHandler(); 
    parser.parse(new File("ornek.xml"), handler);
  }
}


// Tüm XML dosyasının nasıl işleneceğini belirten ŞABLON SINIFIMIZ
public class SaxHandler extends DefaultHandler {

    public void startDocument() throws SAXException {
        System.out.println("start document   : ");
    }

    public void endDocument() throws SAXException {
        System.out.println("end document     : ");
    }

    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {

        System.out.println("start element    : " + qName);
    }

    public void endElement(String uri, String localName, String qName) throws SAXException {
        System.out.println("end element      : " + qName);
    }

    public void characters(char ch[], int start, int length) throws SAXException {
        System.out.println("start characters : " + new String(ch, start, length));
    }
}


Hemen aşağıdaki sonucu üretir:

start document :
start element : root
characters :

start element : child
characters :

start element : grandchild
characters : text 1
end element : grandchild
characters :

end element : child
characters :

start element : child
characters :

start element : grandchild
characters : text 2
end element : grandchild
characters :

end element : child
characters :

end element : root
end document :


Eğer XML satırlarını Child sınıfından nesneler olacak şekilde üretmek isteseydik


// Child sınıfımız aşağıdaki gibi sadece grandchild etiketinin değerini taşıyacak.
class Child {
  public String GrandChild;
  public setGrandChild(String _grandChild){
    this.GrandChild = _grandChild;
  }
}


public class ChildHandler extends DefaultHandler{
    private List cocuklar;
    private Child islenenCocuk;
    private StringBuilder tumXML;
    
    public List getCocuklar(){
        return this.cocuklar;
    }

// Bu sınıf XML etiketinin içindeki kısmını verecek. 
// Örneğin: <grandchild>Ahmet Emmi</grandchild> etiketindeki 
// Ahmet Emmi kısmını characters metodu verecek.
    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        super.characters(ch, start, length);
        tumXML.append(ch, start, length);
    }

// XML dosyasının ROOT elemenanın okuduğumuz metodumuz startDocument olacak.
    @Override
    public void startDocument() throws SAXException {
        super.startDocument();
        cocuklar = new ArrayList();
        tumXML = new StringBuilder();
    }

// Her bir etiketi (element) okumaya başladığımız an: startElement
    @Override
    public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException {
        super.startElement(uri, localName, name, attributes);
        if (localName.equalsIgnoreCase("child")){
            this.islenenCocuk = new Child();
        }
    }


// XML etiketini okuma işi bitince (Tek bir etiketi)
    @Override
    public void endElement(String uri, String localName, String name) throws SAXException {
        super.endElement(uri, localName, name);

        // islenenCocuk eğer başlatılmışsa. 
        // Yani child etiketi okunmaya başlanmışsa islenenCocuk null değildir artık.
        if (this.islenenCocuk != null){

            // eğer bu eleman grandchild ise
            if (localName.equalsIgnoreCase("grandchild")) 
            {
                islenenCocuk.setGrandChild(builder.toString());
            } 
            else if (localName.equalsIgnoreCase("child"))
            {
                cocuklar.add(islenenCocuk);
            }

            // Eğer bir etiketi daha işlediysek StringBuilder dan türettiğimiz
            // ve içinde metin bilgisini tutan değişkeni boşaltıyoruz.
            tumXML.setLength(0);    
        }
    }
}


Hepsi bittiyse bir de bu adresi okuyarak pekiştirin derim.

XmlPullParser

Yapı SAX'a nispetle daha basit.
	public void ReadXml() throws XmlPullParserException {
// Android için res klasörünün içindeki xml klasörünün içindeki countries.xml dosyası
		XmlPullParser parser = getResources().getXml(R.xml.countries);

// parser oluşturuldu. Acaba hangi elementteyiz? Bunu getEventType() metoduyla çekiyoruz
// START_DOCUMENT, END_DOCUMENT, START_TAG,TEXT,COMMENT v.s. olacaktır.
		int eventType = parser.getEventType();

// XML'imizin sonuna gelene dek while yapalım
		while (eventType != XmlPullParser.END_DOCUMENT) {
			try {

// Olaki şu an elimizdeki element TEXT tir (yani xml elementinin içidir(değeridir))
				if (eventType == XmlPullParser.TEXT) {
					CharSequence cs = parser.getText();parser.setInput(inputStream, inputEncoding)
// Log ekranında içeriği görelim
					Log.i("xml read", cs.toString());
				}

//Bir sonraki XML elementine geçelim
				eventType = parser.next();
			} catch (Exception e) {
				e.printStackTrace();
			}

		}