2010-09-29 11 views
5

Tengo que analizar una estructura XML en JAVA usando el analizador SAX.Analizando una estructura XML con una cantidad desconocida de recurrencias usando SAX

El problema es que la estructura es recursiva con un recuento de recursiones no especificado. Esto todavía no es tan importante, el problema es que no puedo aprovechar la funcionalidad del espacio de nombres XML y las etiquetas son las mismas en todos los niveles de recursión.

Aquí hay un ejemplo de la estructura.

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

Como puede ver, hay una recursividad, mejor un número indefinido de recursiones. Ahora mi problema es cómo extraer todos los datos para cada recursión y guardarlos en un HashMap por ejemplo.

pude definir un ContentHandler para la ocurrencia de Tags y tienen que extraer el contenido en una HashMap y poner de nuevo en un maestro HashMap definido en el controlador principal de contenido, pero no estoy seguro de calor para hacer esto.

¿Cómo se extrae y guarda el contenido de una estructura XML recursiva sin utilizar espacios de nombres?

+0

¿Para qué necesitas las claves del HashMap? un valor de atributo? – LarsH

+0

Sí, las claves serán los valores de los atributos. –

Respuesta

3

Echa un vistazo this set of Javaworld articles on using SAX. Demuestra una forma fácil de analizar una estructura XML recursiva utilizando SAX. Crea una máquina de estado que muestra para cada elemento qué elementos puede contener. A medida que su contentHandler atraviesa el xml mantiene una pila que muestra en qué elemento se encuentra actualmente.

+0

Muchas gracias. Esto es exactamente lo que estaba buscando. –

+0

+1 Ese enlace fue especialmente útil. –

0

Si desea analizar XML a través de SAX recursivamente, debe usar Apilar y comprobar la profundidad en su estructura XML. Por mi estructura XML en este formato (. Profundidad máxima es de 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> 

He utilizado este pseudocódigo Java y funciona bastante bien en mi aplicación para Android (por la profundidad conocida). Si no conoce la cantidad de recurrencias y no conoce la profundidad, puede simplemente editar mi código y, en lugar de 3 objetos ArrayList (y 3 objetos Categoría), puede usar una colección dinámica (por ejemplo, ArrayList<ArrayList<Category>>) y ponga ArrayList<Category> en el índice ArrayList<ArrayList<Category>> using, que presenta el método 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(); 
    } 
} 
Cuestiones relacionadas