SORU
22 EYLÜL 2011, PERŞEMBE


Ne zaman SAX StAX üzerinden seçmeliyim?

SAX ve StAX gibi xml ayrıştırıcıları izle, daha hızlı ve daha fazla bellek ayrıştırıcıları DOM ayrıştırıcısı gibi ağaç yapısı bir bina daha verimli. SAX bir itme ayrıştırıcı, gözlemci deseni (da dinleyici desen olarak adlandırılır) bir örnek değil yani. SAX orada ilk, ama sonra geldi StAX - bir çekme ayrıştırıcı, temelde yineleyici bir desen gibi çalışıyor yani.

SAX üzerinde her yerde StAX tercih etmek için bir çok neden bulabilirsiniz, ama genellikle aşağı kaynar: "kullanımı kolay".

Java ile JAXP StAX öğretici DOM arasındaki orta olarak belli belirsiz sundu ve SAX: "SAX DOM daha kolay ve daha verimli". Ancak, hiç SAX daha StAX daha yavaş veya daha az olacak herhangi bir ipucu bellek verimli buldum.

Bu beni meraklandırdı:yerine SAX StAX seçmek için herhangi bir sebep var mı?

CEVAP
23 EYLÜL 2011, Cuma


Genel bakış
XML belgeleri aynı element adları ve ad mastar derinlik (özyinelemeli) çeşitli yerlerde, farklı anlamı olan, ve ortaya çıkabilecek hiyerarşik belgelerdir. Normal olarak, büyük sorunların çözümü, küçük sorunları bölün. XML ayrıştırma bağlamında, bu yöntem XML için özel XML belirli kısımları ayrıştırma anlamına gelir. Örneğin, mantık tek parça adresi ayrıştırma:

<Address>
    <Street>Odins vei</Street>    
    <Building>4</Building>
    <Door>b</Door>
</Address>

yani bir yöntem olurdu

AddressType parseAddress(...); // A

ya

void parseAddress(...); // B

mantığınız bir yerde, XML giriş argümanlar alır ve bir nesne döndürmek (B sonucu bir alan daha sonra getirilebilir).

SAXSAX '' XML events . iter sana bağlı XML olaylar programı / data nereye ait belirlemek için gidiyor.

// method in stock SAX handler
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException
    // .. your logic here for start element
}

Bir 'Yapı' start element, aslında bir Adres ayrıştırma ve XML olayı güzergah Adres yorumlamak kimin yöntemi olduğunu belirlemek gerekir.

StAXStAX '' XML events çekiyorkarar sizin programınızı / XML olayları almak için veri belirlemek için gidiyor.

// method in standard StAX reader
int event = reader.next();
if(event == XMLStreamConstants.START_ELEMENT) {
    // .. your logic here for start element
}

Tabii ki, her zaman bir 'Yapı' Adres yorumlamak için olan yöntemi olay. almak isterim

Tartışma

Bu SAX için tipik olarak, B yöntemine çevirir, ve StAX için Bir yöntem. Buna ek olarak, SAX StAX Bir çok olayları (XMLStreamReader örneği geçerek) verebilir ise B tek tek XML olayları vermek zorundadır.

Böylece B ilk ayrıştırma önceki durumunu kontrol edin ve her bir XML olayı işlemek ve devlet (alana) saklayın. Yöntemi, sadece memnun kadar XML olayların hepsini birden XMLStreamReader birden çok kez erişerek işleyebilir.

SonuçStAX XML yapısı göre yapısı (veri bağlama) ayrıştırma kodu sağlarne olduğu belli olmayan bir ilişki için SAX, 'devletin' örtülü ' program akışı için StAX, SAX, her zaman ihtiyaç korumak için bir çeşit devlet değişken rota akışına göre devlet, en olay çağırır.

StAX ama basit belgeler için tavsiye ederim. Bir iyileştirme daha sonra SAX için hareket (ama muhtemelen o zamana kadar ikili gitmek isteyecek) değil.

StAX kullanarak: ayrıştırılırken bu desen izleyin

public MyDataBindingObject parse(..) { // provide input stream, reader, etc

        // set up parser
        // read the root tag to get to level 1
        XMLStreamReader reader = ....;

        do {
            int event = reader.next();
            if(event == XMLStreamConstants.START_ELEMENT) {
              // check if correct root tag
              break;
            }

            // add check for document end if you want to

        } while(reader.hasNext());

        MyDataBindingObject object = new MyDataBindingObject();
        // read root attributes if any

        int level = 1; // we are at level 1, since we have read the document header

        do {
            int event = reader.next();
            if(event == XMLStreamConstants.START_ELEMENT) {
                level  ;
                // do stateful stuff here

                // for child logic:
                if(reader.getLocalName().equals("Whatever1")) {
                    WhateverObject child = parseSubTreeForWhatever(reader);
                    level --; // read from level 1 to 0 in submethod.

                    // do something with the result of subtree
                    object.setWhatever(child);
                }

                // alternatively, faster
                if(level == 2) {
                    parseSubTreeForWhateverAtRelativeLevel2(reader);
                    level --; // read from level 1 to 0 in submethod.

                    // do something with the result of subtree
                    object.setWhatever(child);
                }


            } else if(event == XMLStreamConstants.END_ELEMENT) {
                level--;
                // do stateful stuff here, too
            }

        } while(level > 0);

        return object;
}

Bu submethod aynı yaklaşımı kullanır, yani sayma seviyesi:

private MySubTreeObject parseSubTree(XMLStreamReader reader) throws XMLStreamException {

    MySubTreeObject object = new MySubTreeObject();
    // read element attributes if any

    int level = 1;
    do {
        int event = reader.next();
        if(event == XMLStreamConstants.START_ELEMENT) {
            level  ;
            // do stateful stuff here

            // for child logic:
            if(reader.getLocalName().equals("Whatever2")) {
                MyWhateverObject child = parseMySubelementTree(reader);
                level --; // read from level 1 to 0 in submethod.

                // use subtree object somehow
                object.setWhatever(child);
            }

            // alternatively, faster, but less strict
            if(level == 2) {
              MyWhateverObject child = parseMySubelementTree(reader);
                level --; // read from level 1 to 0 in submethod.

                // use subtree object somehow
                object.setWhatever(child);
            }


        } else if(event == XMLStreamConstants.END_ELEMENT) {
            level--;
            // do stateful stuff here, too
        }

    } while(level > 0);

    return object;
}

Ve sonunda olan temel türler okuyacak bir seviyeye ulaşmak.

private MySetterGetterObject parseSubTree(XMLStreamReader reader) throws XMLStreamException {

    MySetterGetterObject object = new MySetterGetterObject();
    // read element attributes if any

    int level = 1;
    do {
        int event = reader.next();
        if(event == XMLStreamConstants.START_ELEMENT) {
            level  ;

            // assume <FirstName>Thomas</FirstName>:
            if(reader.getLocalName().equals("FirstName")) {
               // read tag contents
               String text = reader.getElementText()
               if(text.length() > 0) {
                    object.setName(reader.getElementText())
               }
               level--;

            } else if(reader.getLocalName().equals("LastName")) {
               // etc ..
            } 


        } else if(event == XMLStreamConstants.END_ELEMENT) {
            level--;
            // do stateful stuff here, too
        }

    } while(level > 0);

    return object;
}

Bu oldukça basittir ve yanlış anlamaları için bir oda var. Sadece seviye doğru indirim için unutma

Karakterler beklenen ama karakter içermelidir bazı etiketinde bir ELEMAN_SONU aldıktan sonra A. (yukarıdaki desen):

<Name>Thomas</Name>

yerine

<Name></Name>

Aynı kayıp ağacı için de geçerlidir, siz anladınız.

Başlangıç öğeleri olarak adlandırılan subparsing yöntemleri, ve karşılık gelen sonunda döner eleman arıyorum B. sonra, yani ayrıştırıcı bir seviye yöntemi aramadan önce daha düşük (yukarıdaki desen).

Not Bu yaklaşımın tamamen 'gözardı' boşluk çok daha sağlam bir uygulama için. yok sayıyor

Edit: Eklendi bakış, örnek eklendi, desen örnekte dönüş türü eklendi. Eklenen metin daha sağlam kullanım.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • dirkgently1

    dirkgently1

    13 NİSAN 2006
  • Eric Anthony

    Eric Anthony

    13 AĞUSTOS 2011
  • Mr. H

    Mr. H

    1 Temmuz 2012