views:

428

answers:

3

I'm having a problem accessing the contents of an XML document. My goal is this: Take an XML source and parse it into a fair equivalent of an associative array, then store it as a persistable object.

the xml is pretty simple:

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

Basic java class below. I'm pretty much just calling save(xml) after http response above. Yes, the xml is properly formatted.

    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();
    }

The code above is the work in progress, and is most likely heavily flawed. However, I have been at this for days now. I can never seem to get all child nodes, or the name / value pair. When I print out the vector as a string, I usually end up with results like this: [{ = root, = element}] and that's it. No "category_id", no "name"

Ideally, I would end up with something like [{1 = cars, 2 = boats}]

Any help is appreciated.

Thanks

A: 

Here's a fixed version of your program. Changes that I made are as follows:

  • I removed the DocBuilder-stuff from the save() method. These calls are needed to construct a new Document. Once you have such an object (and you do since it is passed in as an argument) you don't need the DocumentBuilder anymore. A proper use of DocumentBuilder is illustrated in the main method, below.
  • _node,_element need not be fields. They get new values with each pass through the loop inside save so I made them local variables. In addition I changed their names to category and name to reflect their association with the elements in the XML document.
  • There's never a need to create a new String object by using new String(). A simple "" in enough (see the initialization of the category and name variables).
  • Instead of looping over everything (via "*") the loop now iterates over element elements. Then there is a an inner loop that iterates over the children of each element, namely: its category_id and name elements.
  • In each pass of the inner we set either the category or the name variable depending on the name of the node at hand.
  • The actual value that is set to these variables is obtained by via node.getTextContent() which returns the stuff between the node's enclosing tags.

class 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();
     }
  }

Here's a main method:

  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);
  }
Itay
A: 

Thank you so much. With only slight modification I was able to do exactly what I was looking for.

Here are the modifications I had to do: Even though I am building in 1.5, getTextContent was not available. I had to use category = n.getFirstChild().getNodeValue(); to obtain the value of each node. Though there may have been a simple solution like updating my build settings, I am not familiar enough with BB requirements to know when it is safe to stray from the default recommended build settings.

In the main, I had to alter this line:

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

so that it was reading from an InputStream delivered from my web server, and not necessarily a local file - even though I wonder if storing the xml local would be more efficient than storing a vector full of hash tables. ...

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

Obviously I skipped over the HTTP connection portion for the sake of keeping this readable.

Your help has saved me a full weekend of blind debugging. Thank you very much! Hopefully this post will help someone else as well.

Greg
A: 

Hi..

in the above code, i want to use "Document xml = docBuilder.parse(new File("input.xml"));". This file is in rsc folder or think C:/input.xml. But it is giving error

"Multiple markers at this line - The method parse(InputStream) in the type DocumentBuilder is not applicable for the arguments (File) - The constructor File(String) is undefined"

so what should i do????

please reply as soon as possible

Ravi Krishna.P