Parse XML file on BlackBerry

Solution 1:

Parsing XML in Blackberry

Simple API for XML (SAX) was developed by the members of a public mailing list (XML-DEV).It gives an event based approach to XML parsing. It means that instead of going from node to node, it goes from event to event. SAX is an event driven interface. Events include XML tag, detecting errors etc, J2ME SAX - see BlackBerry/J2ME - SAX parse collection of objects with attributes

XML pull parser - It is optimal for applications that require fast and a small XML parser. It should be used when all the process has to be performed quickly and efficiently to input elements kXML - J2ME pull parser - see Better approach for XML Creation in Blackberry

Parsing XML with JSON

Blackberry standard for JSON parsing is JSON ME

No idea... JSON can be represented and transported as a XML, but not vice versa.

XML (Extensible Markup Language) is a set of rules for encoding documents electronically. It is defined in the XML 1.0 Specification produced by the W3C, and several other related specifications, all gratis open standards.

XML sample:

<?xml version="1.0" encoding='UTF-8'?>
<painting>
  <img src="madonna.jpg" alt='Foligno Madonna, by Raphael'/>
  <caption>This is Raphael's "Foligno" Madonna, painted in
    <date>1511</date>–<date>1512</date>.
  </caption>
</painting>

JSON (an acronym for JavaScript Object Notation) is a lightweight text-based open standard designed for human-readable data interchange. It is derived from the JavaScript programming language for representing simple data structures and associative arrays, called objects (the “O” in “JSON”). Despite its relationship to JavaScript, it is language-independent, with parsers available for virtually every programming language.

JSON sample:

{
     "firstName": "John",
     "lastName": "Smith",
     "age": 25,
     "address": {
         "streetAddress": "21 2nd Street",
         "city": "New York",
         "state": "NY",
         "postalCode": "10021"
     },
     "phoneNumber": [
         { "type": "home", "number": "212 555-1234" },
         { "type": "fax", "number": "646 555-4567" }
     ]
 }

Basically if your XML is a strong equivalent of JSON, like:

<Person>
  <firstName>John</firstName>
  <lastName>Smith</lastName>
  <age>25</age>
  <address>
    <streetAddress>21 2nd Street</streetAddress>
    <city>New York</city>
    <state>NY</state>
    <postalCode>10021</postalCode>
  </address>
  <phoneNumber type="home">212 555-1234</phoneNumber>
  <phoneNumber type="fax">646 555-4567</phoneNumber>
</Person>

there is a possibility to parse such XML with JSON.

Solution 2:

Parsing is usually done using a 3rd party library that can be loaded into a project. If you're using XML, I've used a library called the kXML parser. Setting it up can be a pain, but there are instructions on how to set it up here -

http://supportforums.blackberry.com/t5/Java-Development/Tutorial-How-To-Use-3rd-Party-Libraries-in-your-Applications/m-p/177543

http://www.craigagreen.com/index.php?/Blog/blackberry-and-net-webservice-tutorial-part-1.html

Using kXML is pretty straight forward. This tutorial here explains how to parse an XML file -

http://www.roseindia.net/j2me/kxml/j2me-xml-parser.shtml

Edit: Whoops, the first tutorial in the next post has a pretty comprehensive overview on xml parsing on kxml2. So my post's kinda redundant.

Solution 3:

/**
 * class is used to parse the XML response from the server
 */
package com.rtcf.util;

import java.io.IOException;
import java.io.InputStream;
import java.util.Vector;

import javax.microedition.io.Connector;
import javax.microedition.io.file.FileConnection;

import net.rim.device.api.i18n.DateFormat;
import net.rim.device.api.i18n.SimpleDateFormat;
import net.rim.device.api.xml.parsers.ParserConfigurationException;
import net.rim.device.api.xml.parsers.SAXParser;
import net.rim.device.api.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import com.rtcf.bean.ItemBean;
import com.rtcf.bean.SpvItemBean;

import com.rtcf.bean.ItemCategoryMappingsBean;
import com.rtcf.screen.FirstSyncProgressScreen;
import com.rtcf.util.db.SQLManagerSync1;


public class ItemXMLParser extends DefaultHandler  {

    //private Statement statement = null;   
    public int currentpage = 1, totalpage = 1;
    public int maxWidth; 

    private final int BATCH_COUNT = 100;

    private String tempVal;

    long startT, endT;
    private Vector vecItem = new Vector(BATCH_COUNT);
    private Vector vecItemCategoryMapping = new Vector(BATCH_COUNT);

    //constructor
    int roomInsCount = 0;
    int roomMapInsCount = 0;

    int TBL_FACILITYCount = 0;
    int insCount = 0;

    private FirstSyncProgressScreen fsps;
    private SQLManagerSync1 tempDb;

    //constructor   
    public ItemXMLParser(FirstSyncProgressScreen fsps, SQLManagerSync1 tempDb){
        this.fsps=fsps;
        this.tempDb = tempDb;
        getData();
    }

    /**
     * Method returns the list of data in a vector (response objects) 
     * @param url
     * @return Vector
     */
    public void getData(){

        FileConnection fconn = null;
        InputStream inputStream = null;     

        try{

            // String url = "http://10.10.1.10/LDS/abcd.xml";
            // Logger.debug("HttpConParamUtil.getWebData -------------------- "+url);
             // HttpConParamUtil.getWebData(url, param, this, method);
             // HttpConUtilSingle.getWebData(url, this);
            //Logger.debug("response size -------------- "+response.size());


            String fileUrl = "file:///SDCard/Item.xml";
            fconn = (FileConnection)Connector.open( fileUrl, Connector.READ);


            //get a factory
            SAXParserFactory spf = SAXParserFactory.newInstance();

            try {

                inputStream = fconn.openInputStream();              

                //get a new instance of parser
                SAXParser sp = spf.newSAXParser();

                //parse the file and also register this class for call backs
                sp.parse(inputStream, this);

            }catch(SAXException se) {
                Logger.error( "  startDocument "+se.getMessage(), se);          

            }catch (IOException ie) {
                Logger.error( "  startDocument "+ie, ie);           

            } catch (ParserConfigurationException e) {
                // TODO Auto-generated catch block
                Logger.error( "  startDocument "+e, e);         

            } catch (Exception e) {
                // TODO Auto-generated catch block
                Logger.error( "  "+e, e);           

            }

        }
        catch (Exception e) {
            //Logger.debug("### Exception in getData - "+e.getMessage()+" "+e.getClass());
            //Dialog.inform("### Exception in getData - "+e.getMessage()+" "+e.getClass());
        }finally{

            try{
                if(inputStream != null){inputStream.close(); }
            }catch(Exception e){}           

            try{
                if(fconn != null){fconn.close(); }
            }catch(Exception e){}
        }
        //return response;
    }// end getData

     //===========================================================
    // Methods in SAX DocumentHandler 
    //===========================================================

     public void startDocument () throws SAXException{
         //Logger.debug("################# In startDocument");
            DateFormat timeFormat = new SimpleDateFormat("HH.mm.ss");
            startT = System.currentTimeMillis();

            // String currentTime = timeFormat.format(date);
            Logger.debug("########## ----------Start time:" + startT);


     }

     public void endDocument () throws SAXException{

         if( vecItemCategoryMapping.size() > 0){
             //fsps.updatedProgress2(22, "Inserting TBL_ITEM_CATEGORY_MAPPING Record ");
                Logger.debug("Populate TBL_ITEM_CATEGORY_MAPPING...");
                tempDb.InsertTbl_item_category_mapping(vecItemCategoryMapping);
                vecItemCategoryMapping = null;
                //vecItemCategory = new Vector(BATCH_COUNT);

            }
         if( vecItem.size() > 0){
            // fsps.updatedProgress2(25, "Inserting TBL_ITEM Record ");
                Logger.debug("Populate TBL_ITEM...");
                tempDb.InsertTbl_item(vecItem);
                vecItem = null;
                //vecItem = new Vector(BATCH_COUNT);

            }

     }

     //Event Handlers
     public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
         //Logger.debug("################# In startElement qName : "+qName);

            if(qName.equals("TBL_ITEM_CATEGORY_MAPPING")){
                Logger.debug("Populate TBL_ITEM_CATEGORY_MAPPING...");
                populateTblItemCategoryMapping(attributes);
            }
            if(qName.equals("TBL_ITEM")){
                Logger.debug("Populate TBL_ITEM...");
                populateTblItem(attributes);
            }

     }



        public void endElement(String uri, String localName, String qName) throws SAXException {

            if(qName.equals("TBL_ITEM_CATEGORY_MAPPING")&& vecItemCategoryMapping.size() == BATCH_COUNT){
                Logger.debug("Populate TBL_ITEM_CATEGORY...");
                tempDb.InsertTbl_item_category_mapping(vecItemCategoryMapping);
                vecItemCategoryMapping = null;
                vecItemCategoryMapping = new Vector(BATCH_COUNT);

            }
            if(qName.equals("TBL_ITEM")&& vecItem.size() == BATCH_COUNT){
                Logger.debug("Populate TBL_ITEM...");
                tempDb.InsertTbl_item(vecItem);
                vecItem = null;
                vecItem = new Vector(BATCH_COUNT);

            }
        }


    public void characters(char[] ch, int start, int length) throws SAXException {
        //Logger.debug("################# In characters");
        tempVal = new String(ch,start,length);
    }


     // reads the xml file and saves the ItemCategoryMappingBean data and adds to vecItemCategoryMapping

    private void populateTblItemCategoryMapping(Attributes attributes) {

        try{
            ItemCategoryMappingsBean ItemCategoryMappingBean = new ItemCategoryMappingsBean();

                try{
                    if((attributes.getValue("itemCategoryId"))!=null)
                    ItemCategoryMappingBean.itemCategoryId = Integer.parseInt(attributes.getValue("itemCategoryId"));
                    else {
                        ItemCategoryMappingBean.itemCategoryId = -1;
                    }
                    if((attributes.getValue("itemId"))!= null)
                    ItemCategoryMappingBean.itemId = Integer.parseInt(attributes.getValue("itemId"));
                    else {
                        ItemCategoryMappingBean.itemId = -1;
                    }

                    if((attributes.getValue("ddlFlag"))!=null) 
                        ItemCategoryMappingBean.ddlFlag = attributes.getValue("ddlFlag").charAt(0);
                        else {
                            ItemCategoryMappingBean.ddlFlag = 'I';
                        }

                    //ItemCategoryMappingBean.categoryName = (attributes.getValue("categoryName"));
                    Logger.debug("#######  populateTblItemCategoryMapping ");
                }catch(NumberFormatException nfe){
                    Logger.error("### NumberFormatException SAXXMLParser -->> populateTblItemCategoryMapping() - "+nfe.getMessage(),nfe);
                                    }
                vecItemCategoryMapping.addElement(ItemCategoryMappingBean);

        }catch(Exception e){
            Logger.error("ItemXMLParser -->> populate  TblItemCategory() - "+e.getMessage(),e);
            }   

    }


    // reads the xml file and saves the ItemBean data and adds to vecItem

    private void populateTblItem(Attributes attributes) {
        // TODO Auto-generated method stub
        ItemBean itemBean= new ItemBean();
        try{

        try{

            itemBean.itemId = Integer.parseInt(attributes.getValue("itemId"));

            if((attributes.getValue("videoURL"))!=null)
            itemBean.videoURL = (attributes.getValue("videoURL"));
            else {
                itemBean.videoURL = "";
            }


            if((attributes.getValue("itemDescription"))!=null)
            itemBean.itemDescription = (attributes.getValue("itemDescription"));
            else {
                itemBean.itemDescription = "";
            }

            if((attributes.getValue("itemProcedure"))!=null)
            itemBean.itemProcedure = (attributes.getValue("itemProcedure"));
            else {
                itemBean.itemProcedure = "";
            }

            if((attributes. getValue("itemStandard"))!=null)
            itemBean.itemStandard = (attributes.getValue("itemStandard"));
            else {
                itemBean.itemStandard = "";
            }

            if((attributes.getValue("weight"))!=null)
            itemBean.weight = (attributes.getValue("weight"));
            else {
                itemBean.weight = "";
            }

            if((attributes.getValue("ddlFlag"))!=null) 
                itemBean.ddlFlag = attributes.getValue("ddlFlag").charAt(0);
                else {
                    itemBean.ddlFlag = 'I';
                }

            vecItem.addElement(itemBean);
            Logger.debug("#######  populate  TblItem ");
        }catch(NumberFormatException nfe){
            Logger.error("### NumberFormatException SAXXMLParser -->> populateTblItemCategoryMapping() - "+nfe.getMessage(),nfe);
                            }


}catch(Exception e){
    Logger.error("ItemXMLParser -->> populateTblItemCategory() - "+e.getMessage(),e);
    }   
    }


}// end XMLParser

Solution 4:

This link is from the blackberry site : http://www.blackberry.com/knowledgecenterpublic/livelink.exe/fetch/2000/348583/800332/800599/How_To_-_Use_the_XML_Parser.html?nodeid=820554&vernum=0

I made the following changes to make it work (Yea...BB dev site is pretty annoying sometimes..)

in the method updateField() - Make sure to add the ui thread, otherwise no change will occur.

 UiApplication.getUiApplication().invokeLater(new Runnable() 
    {
        public void run()
        {
             String title="Title";
                _screen.add(new RichTextField(node+" : "+element));

                if(node.equals(title))
                {
                    _screen.add(new SeparatorField());
                }
        }
    });

Also if you want to read your .xml file locally (like in your folder for example) - You obviously don't need a localhost connection with a port. Either way, when I ran it with local://test.xml and I kept getting a connection error. Went forum jumping and found this little solution. (Yes my .xml file is called madhouse). Oh and the "test.xml.XMLDemoScreen - is packageName and class name.

Class cl = Class.forName("test.xml.XMLDemoScreen");
InputStream in = cl.getResourceAsStream("/madhouse.xml");
doc = docBuilder.parse(in);

Hope that helps! :D