How do you move and store XML in a Blackberry Java application?

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

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>

      

The main java class is below. I almost just call save (xml) after the HTTP response above. Yes, the xml is formatted correctly.

    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 above code is work in progress and most likely badly flawed. However, I have been doing this for several days now. I can never get all the child nodes or a name / value pair. When I print a vector as a string, I usually get results like this: [{= root, = element}] and that's it. No "category_id", no "name"

Ideally, I would get something like [{1 = cars, 2 = boats}]

Any help is appreciated.

thanks

+2


source to share


3 answers


Here's a fixed version of your program. The changes I have made are as follows:

  • I removed the DocBuilder stuff from the method save()

    . These calls are needed to create a new one Document

    . Once you have an object like this (and you do, since it was passed as an argument), you won't need it anymore DocumentBuilder

    . The correct usage is DocumentBuilder

    shown below in the method main

    .
  • _node, _element doesn't have to be fields. They get new values ​​with each pass through the loop inside save

    , so I made them local variables. I also changed their names to category

    and name

    to reflect their relationship to elements in the XML document.
  • You should never need to create a new String object with new String()

    . Simple ""

    enough (see variable initialization category

    and name

    ).
  • Instead of "*"

    iterating over everything (through ), the loop is now iterating over the elements element

    . Then there is an inner loop that iterates over the children of each element, namely its elements category_id

    and name

    .
  • In each pass of the internal value, we set either a variable category

    or name

    depending on the node name.
  • The actual value set for these variables is obtained via node.getTextContent()

    , which returns stuff between the node 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 the 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);
  }

      

+1


source


Thank you very much. With a few minor changes, I was able to do exactly what I was looking for.

Here are the changes I had to make: Although I'm building in 1.5, getTextContent is not available. I had to use category = n.getFirstChild (). GetNodeValue (); to get the value of each node. While there might be a simple solution such as updating my build settings, I don't know enough about BB's requirements to know when to safely deviate from the default recommended build settings.

I basically had to change this line:

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

      



so it was reading from an InputStream supplied from my webserver and not necessarily a local file, even if I'm wondering if storing a local XML file would be more efficient than storing a vector full of hash tables. ...

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

      

Obviously I missed the HTTP connection part to keep this readable.

Your help saved me this whole weekend of blind debugging. Many thanks! Hope this post helps someone else too.

0


source


 //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 );

      

0


source







All Articles