2010-04-10 17 views
2

J'ai un problème pour accéder au contenu d'un document XML. Mon objectif est le suivant: Prenez une source XML et analysez-la en un équivalent équitable d'un tableau associatif, puis stockez-la en tant qu'objet persistant.Comment traverser et stocker XML dans l'application Blackberry Java?

le xml est assez simple:

<root> 
<element> 
    <category_id>1</category_id> 
    <name>Cars</name> 
</element> 
<element> 
    <category_id>2</category_id> 
    <name>Boats</name> 
</element> 
</root> 

classe de base java ci-dessous. Je suis à peu près en train d'appeler save (xml) après la réponse http ci-dessus. Oui, le format XML est correctement formaté.

import java.io.IOException; 
    import java.util.Hashtable; 

    import org.w3c.dom.Document; 
    import org.w3c.dom.Node; 
    import org.w3c.dom.NodeList; 

    import java.util.Vector; 
    import net.rim.device.api.system.PersistentObject; 
    import net.rim.device.api.system.PersistentStore; 
    import net.rim.device.api.xml.parsers.DocumentBuilder; 
    import net.rim.device.api.xml.parsers.DocumentBuilderFactory; 

public class database{ 
     private static PersistentObject storeVenue; 
     static final long key = 0x2ba5f8081f7ef332L; 
     public Hashtable hashtable; 
     public Vector venue_list; 
     String _node,_element; 

    public database() 
    { 
     storeVenue = PersistentStore.getPersistentObject(key); 
    } 

    public void save(Document xml) 
    { 
      venue_list = new Vector(); 
     storeVenue.setContents(venue_list); 


     Hashtable categories = new Hashtable(); 


     try{ 

      DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory. newInstance(); 
      DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); 
      docBuilder.isValidating(); 

      xml.getDocumentElement().normalize(); 

      NodeList list=xml.getElementsByTagName("*"); 
      _node=new String(); 
      _element = new String(); 

      for (int i=0;i<list.getLength();i++){ 

       Node value=list.item(i).getChildNodes().item(0); 
       _node=list.item(i).getNodeName(); 
       _element=value.getNodeValue(); 

       categories.put(_element, _node); 
      } 

     } 
     catch (Exception e){ 
      System.out.println(e.toString()); 
     } 

     venue_list.addElement(categories); 


     storeVenue.commit(); 
    } 

Le code ci-dessus est le travail en cours, et est très probablement fortement défectueux. Cependant, je suis là depuis des jours. Je n'arrive jamais à obtenir tous les nœuds enfants, ni la paire nom/valeur. Lorsque j'imprime le vecteur sous forme de chaîne, je finis généralement avec des résultats comme celui-ci: [{= root, = element}] et c'est tout. Non "category_id", pas "nom"

Idéalement, je voudrais finir avec quelque chose comme [{1 = voitures, 2 = bateaux}]

Toute aide est appréciée.

Merci

Répondre

1

Voici une version corrigée de votre programme. Les modifications que j'ai apportées sont les suivantes:

  • J'ai supprimé l'élément DocBuilder de la méthode save(). Ces appels sont nécessaires pour construire un nouveau Document. Une fois que vous avez un tel objet (et vous le faites depuis qu'il est passé en argument), vous n'avez plus besoin du DocumentBuilder. Une utilisation correcte de DocumentBuilder est illustrée dans la méthode main, ci-dessous.
  • _node, _element n'a pas besoin d'être des champs. Ils obtiennent de nouvelles valeurs avec chaque passage à travers la boucle à l'intérieur save donc je les ai fait des variables locales. En outre, j'ai changé leurs noms à category et name pour refléter leur association avec les éléments dans le document XML. Il n'est jamais nécessaire de créer un nouvel objet String en utilisant new String(). Un simple "" en assez (voir l'initialisation des variables category et name).
  • Au lieu de boucler tout (via "*") la boucle itère maintenant sur element éléments. Il y a ensuite une boucle interne qui itère sur les enfants de chaque élément, à savoir: ses éléments category_id et name.
  • À chaque passage de l'intérieur, nous définissons la variable category ou la variable name en fonction du nom du nœud en question.
  • La valeur réelle qui est définie pour ces variables est obtenue par l'intermédiaire de node.getTextContent() qui renvoie le contenu entre les balises englobantes du noeud.

classe database:

public class database { 
    private static PersistentObject storeVenue; 
    static final long key = 0x2ba5f8081f7ef332L; 
    public Hashtable hashtable; 
    public Vector venue_list; 

    public database() { 
     storeVenue = PersistentStore.getPersistentObject(key); 
    } 

    public void save(Document xml) { 
     venue_list = new Vector(); 
     storeVenue.setContents(venue_list); 

     Hashtable categories = new Hashtable(); 

     try { 

      xml.getDocumentElement().normalize(); 

      NodeList list = xml.getElementsByTagName("element"); 

      for (int i = 0; i < list.getLength(); i++) { 

       String category = ""; 
       String name = ""; 
       NodeList children = list.item(i).getChildNodes(); 
       for(int j = 0; j < children.getLength(); ++j) 
       { 
       Node n = children.item(j); 
       if("category_id".equals(n.getNodeName())) 
        category = n.getTextContent(); 
       else if("name".equals(n.getNodeName())) 
        name = n.getTextContent(); 
       } 

       categories.put(category, name); 

       System.out.println("category=" + category + "; name=" + name); 
      } 

     } catch (Exception e) { 
      System.out.println(e.toString()); 
     } 

     venue_list.addElement(categories); 

     storeVenue.commit(); 
    } 
    } 

Voici une méthode principale:

public static void main(String[] args) throws Exception { 
    DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory 
     .newInstance(); 
    DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); 
    docBuilder.isValidating(); 

    Document xml = docBuilder.parse(new File("input.xml")); 

    database db = new database(); 
    db.save(xml); 
    } 
0

Merci beaucoup. Avec seulement une légère modification, j'ai été capable de faire exactement ce que je cherchais.

Voici les modifications que j'ai dû faire: Même si je construis dans 1.5, getTextContent n'était pas disponible. J'ai dû utiliser category = n.getFirstChild(). GetNodeValue(); pour obtenir la valeur de chaque noeud. Bien qu'il y ait eu une solution simple comme la mise à jour de mes paramètres de construction, je ne suis pas assez familier avec les exigences de BB pour savoir quand il est prudent de s'éloigner des paramètres de construction recommandés par défaut.

Dans l'ensemble, je devais modifier cette ligne:

Document xml = docBuilder.parse(new File("input.xml")); 

afin qu'il était en train de lire à partir d'un InputStream délivré de mon serveur web, et pas nécessairement un fichier local - même si je me demande si le stockage de la xml local serait plus efficace que de stocker un vecteur plein de tables de hachage. ...

InputStream responseData = connection.openInputStream(); 
Document xmlParsed = docBuilder.parse(result); 

Il est évident que j'ai sauté sur la partie de connexion HTTP pour le bien de garder cela reste lisible.

Votre aide m'a sauvé un week-end complet de débogage aveugle. Merci beaucoup! J'espère que ce message aidera aussi quelqu'un d'autre.

0
//res/xml/input.xml 
private static String _xmlFileName = "/xml/input.xml"; 

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
DocumentBuilder builder = factory.newDocumentBuilder(); 
InputStream inputStream = getClass().getResourceAsStream(_xmlFileName); 
Document document = builder.parse(inputStream);