2010-09-29 2 views
5

Мне нужно проанализировать структуру XML в JAVA с помощью анализатора SAX.Анализ структуры XML с неизвестным количеством рекурсий с использованием SAX

Проблема в том, что структура рекурсивна с неопределенным количеством рекурсий. Это все еще не так уж и важно, большое дело в том, что я не могу воспользоваться функциональностью пространства имен XML, и теги одинаковы на каждом уровне рекурсии.

Вот пример конструкции.

<?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> 

Как вы можете видеть, существует рекурсия, лучше неопределенное количество рекурсий. Теперь моя проблема заключается в том, как извлечь все данные для каждой рекурсии и сохранить ее в файле HashMap.

я мог определить ContentHandler для возникновения Tags и иметь его извлечь содержимое в HashMap и положить его обратно в мастерHashMap, определенной в главном обработчике контента, но я не уверен, что жарко, чтобы сделать это.

Как извлечь и сохранить содержимое рекурсивной структуры XML без использования пространств имен?

+0

Что вам нужно для ключей от HashMap? значение атрибута? – LarsH

+0

Да, ключи будут значениями атрибутов. –

ответ

3

Отъезд this set of Javaworld articles on using SAX. Он демонстрирует простой способ анализа рекурсивной структуры XML с использованием SAX. Он создает машину состояний, показывающую для каждого элемента, какие элементы он может содержать. Когда ваш контентHandler пересекает xml, он держит стек, показывающий, какой элемент он сейчас включен.

+0

Большое спасибо. Это совершенно то, что я искал. –

+0

+1 Эта ссылка была особенно полезна. –

0

Если вы хотите проанализировать XML через SAX рекурсивно, вы должны использовать Stack и проверить глубину в вашей структуре XML. Для моей структуры XML в этом формате (макс. Глубина 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> 

Я использовал Java псевдокод, и она работает очень хорошо в моем Android приложения (для известной глубины). Если вы не знаете количество рекурсий и не знаете глубины, вы можете просто отредактировать мой код и вместо 3 объектов ArrayList (и 3 объекта Category), вы можете использовать одну динамическую коллекцию (например, ArrayList<ArrayList<Category>>) и введите ArrayList<Category> в индекс ArrayList<ArrayList<Category>> с использованием индекса, который представляет метод getDepth().

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(); 
    } 
} 
Смежные вопросы