2010-09-29 11 views
5

Ich muss eine XML-Struktur in JAVA mit dem SAX-Parser analysieren.Parsen einer XML-Struktur mit einer unbekannten Anzahl von Rekursionen mit SAX

Das Problem ist, dass die Struktur rekursiv mit einer nicht angegebenen Anzahl von Rekursionen ist. Dies ist immer noch nicht so eine große Sache, das große Problem ist, dass ich die XML-Namespace-Funktionalität nicht nutzen kann und die Tags auf jeder Rekursionsebene gleich sind.

Hier ist ein Beispiel für die Struktur.

<?xml version="1.0" encoding="UTF-8"?> 
<RootTag> 
    <!-- LOADS OF OTHER TAGS --> 
    <Tags attribute="value"> 
     <Tag attribute="value"> 
      <SomeOtherTag></SomeOtherTag> 
      <Tags attribute="value"> 
       <Tag attribute="value"> 
        <SomeOtherTag></SomeOtherTag> 
        <Tags attribute="value"> 
         <!-- MORE OF THE SAME STRUCTURE --> 
        </Tags> 
       </Tag> 
      </Tags> 
     </Tag> 
    </Tags> 
    <!-- LOADS OF OTHER TAGS --> 
</RootTag> 

Wie Sie sehen können, gibt es eine Rekursion, besser eine undefinierte Anzahl von Rekursionen. Jetzt ist mein Problem, wie man alle Daten für jede Rekursion extrahiert und sie in einem HashMap zum Beispiel speichert.

Ich könnte ein ContentHandler für das Auftreten von Tags definieren und sie den Inhalt in einem HashMap extrahieren und sie in einem MasterHashMap im Haupt Content-Handler definiert setzen zurück, aber ich bin nicht sicher, heiß, dies zu tun.

Wie extrahiere und speichere ich den Inhalt einer rekursiven XML-Struktur, ohne Namespaces zu verwenden?

+0

Was benötigen Sie die Schlüssel der HashMap? ein Attributwert? – LarsH

+0

Ja, die Schlüssel sind die Attributwerte. –

Antwort

3

Auschecken this set of Javaworld articles on using SAX. Es demonstriert eine einfache Möglichkeit, eine rekursive XML-Struktur mit SAX zu analysieren. Es erstellt eine Zustandsmaschine, die für jedes Element anzeigt, welche Elemente es enthalten kann. Während Ihr contentHandler die XML-Datei durchläuft, wird ein Stapel angezeigt, der anzeigt, auf welchem ​​Element er sich gerade befindet.

+0

Vielen Dank. Das ist genau das, wonach ich gesucht habe. –

+0

+1 Dieser Link war besonders hilfreich. –

0

Wenn Sie XML über SAX rekursiv analysieren möchten, müssen Sie Stack verwenden und die Tiefe in Ihrer XML-Struktur überprüfen. Für meine XML-Struktur in diesem Format (max. Tiefe 3):

<Response action='categories'> 
    <Categories> 
     <Category name='{name}' id='{id}' numSubcategories='{num}'> 
      <Category name='{name}' id='{id}' numSubcategories='{num}'> 
       <Category name='{name}' id='{id}' numSubcategories='0'/> 
       ... 
      </Category> 
      ... 
     </Category> 
     ... 
    </Categories> 
</Response> 

benutzen ich diesen Java Pseudo-Code und es funktioniert ziemlich gut in meinem Android-App (für bekannte Tiefe). Wenn Sie die Anzahl der Rekursionen nicht kennen und die Tiefe nicht kennen, können Sie einfach meinen Code bearbeiten und anstelle von 3 ArrayList-Objekten (und 3 Category-Objekten) können Sie eine dynamische Sammlung verwenden (z. B. ArrayList<ArrayList<Category>>) und Setzen Sie ArrayList<Category> in die ArrayList<ArrayList<Category>> mit Index, die getDepth() Methode präsentiert.

public class CategoriesResponse extends Response 
{ 
    private Stack<String> mTagStack = new Stack<String>(); 
    private ArrayList<Category> mCategories1; 
    private ArrayList<Category> mCategories2; 
    private ArrayList<Category> mCategories3; 
    Category mCategory1; 
    Category mCategory2; 
    Category mCategory3; 
    private int mCurrentDepth = 0; 


    public ArrayList<Category> getCategories() 
    { 
     return mCategories1; 
    } 


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

     ... 

     if(localName.equals("Category")) 
     { 
      // push element into the stack 
      mTagStack.push(localName); 

      // get data 
      int id = Integer.parseInt(attributes.getValue("id")); 
      String name = attributes.getValue("name"); 
      int numSubcategories = Integer.parseInt(attributes.getValue("numSubcategories")); 

      // create new Category 
      if(getDepth()==1) 
      { 
       mCategory1 = new Category(id, name); 
       mCategory1.setSubcategoriesSize(numSubcategories); 
       mCategory1.setSubcategories(null); 
       if(mCurrentDepth<getDepth()) mCategories1 = new ArrayList<Category>(); // deeping down so create new list 
      } 
      else if(getDepth()==2) 
      { 
       mCategory2 = new Category(id, name); 
       mCategory2.setSubcategoriesSize(numSubcategories); 
       mCategory2.setSubcategories(null); 
       if(mCurrentDepth<getDepth()) mCategories2 = new ArrayList<Category>(); // deeping down so create new list 
      } 
      else if(getDepth()==3) 
      { 
       mCategory3 = new Category(id, name); 
       mCategory3.setSubcategoriesSize(numSubcategories); 
       mCategory3.setSubcategories(null); 
       if(mCurrentDepth<getDepth()) mCategories3 = new ArrayList<Category>(); // deeping down so create new list 
      } 

      // debug output 
      if(mCurrentDepth<getDepth()) Log.d("SAX_TEST", getPath() + " | " + getDepth() + " | DEEPING DOWN"); 
      else if(mCurrentDepth>getDepth()) Log.d("SAX_TEST", getPath() + " | " + getDepth() + " | DEEPING UP"); 
      else if(mCurrentDepth==getDepth()) Log.d("SAX_TEST", getPath() + " | " + getDepth() + " | STAYING"); 

      // set current depth 
      mCurrentDepth = getDepth(); 
      return; 
     } 
    } 


    public void characters(char[] ch, int start, int length) throws SAXException 
    { 
     super.characters(ch, start, length); 
     ... 
    } 


    public void endElement(String uri, String localName, String qName) throws SAXException 
    { 
     super.endElement(uri, localName, qName); 

     ... 

     if(localName.equals("Category")) 
     { 
      // debug output 
      Log.d("SAX_TEST", "END OF THE ELEMENT IN DEPTH " + getDepth() + " | " + mCurrentDepth); 

      // deeping up so set sublist for current category 
      if(getDepth()!=mCurrentDepth) 
      { 
       if(getDepth()==2) mCategory2.setSubcategories(mCategories3); 
       if(getDepth()==1) mCategory1.setSubcategories(mCategories2); 
      } 

      // add current category to list 
      if(getDepth()==1) 
      { 
       mCategories1.add(mCategory1); 
      } 
      else if(getDepth()==2) 
      { 
       mCategories2.add(mCategory2); 
      } 
      else if(getDepth()==3) 
      { 
       mCategories3.add(mCategory3); 
      } 

      // pop element from stack 
      mTagStack.pop(); 
      return; 
     } 
    } 


    // debug output - write current path 
    private String getPath() 
    { 
     String buffer = ""; 
     Enumeration<String> e = mTagStack.elements(); 
     while (e.hasMoreElements()) 
     { 
      buffer = buffer + "/" + (String) e.nextElement(); 
     } 
     return buffer; 
    } 


    // get current depth of stack 
    private int getDepth() 
    { 
     return mTagStack.size(); 
    } 
}