Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
904 views
in Technique[技术] by (71.8m points)

xml - BlackBerry/J2ME - SAX parse collection of objects with attributes

I have a problem with using the SAX parser to parse a XML file. It is a complex XML file, it is like the following.

    <Objects>
        <Object no="1">
            <field name="PID">ilives:87877</field>
            <field name="dc.coverage">Charlottetown</field>
            <field name="fgs.ownerId">fedoraAdmin</field> 
        </Object>
        <Object no="2">......

I am confused how to get the names in each field, and how to store the information of each object.

import java.util.Enumeration;
import java.util.Hashtable;


public class XMLObject {
 private Hashtable mFields = new Hashtable();
    private int mN = -1;
    public int getN() {
        return mN;
    }
    public void setN(int n) {
        mN = n;
    }
    public String getStringField(String key) {
        return (String) mFields.get(key);
    }
    public void setStringField(String key, String value)
    {
        mFields.put(key, value);
    }
    public String getPID() {
        return getStringField("PID");
    }
    public void setPID(String pid) {
        setStringField("PID", pid);
    }
    public String getDcCoverage() {
        return getStringField("dc.coverage");
    }
    public void setDcCoverage(String dcCoverage) {      
        setStringField("dc.coverage", dcCoverage);
    }
    public String getFgsOwnerId() {
        return getStringField("fgs.ownerId");
    }
    public void setFgsOwnerId(String fgsOwnerId) {
        setStringField("fgs.ownerId", fgsOwnerId);
    }
    public String dccreator() {
        return getStringField("dc.creator");
    }
    public void dccreator(String dccreator) {
        setStringField("dc.creator", dccreator);
    }
    public String getdcformat() {
        return getStringField("dc.format");
    }
    public void setdcformat(String dcformat) {
        setStringField("dc.format", dcformat);
    }
    public String getdcidentifier() {
        return getStringField("dc.identifier");
    }
    public void setdcidentifier(String dcidentifier) {
        setStringField("dc.identifier", dcidentifier);
    }
    public String getdclanguage() {
        return getStringField("dc.language");
    }
    public void setdclanguage(String dclanguage) {
        setStringField("dc.language", dclanguage);
    }
    public String getdcpublisher()
    {
        return getStringField("dc.publisher");
    }
    public void setdcpublisher(String dcpublisher)
    {
        setStringField("dc.publisher",dcpublisher);
    }
    public String getdcsubject()
    {
        return getStringField("dc.subject");
    }
    public void setdcsubject(String dcsubject)
    {
        setStringField("dc.subject",dcsubject);
    }
    public String getdctitle()
    {
        return getStringField("dc.title");
    }
    public void setdctitle(String dctitle)
    {
        setStringField("dc.title",dctitle);
    }
    public String getdctype()
    {
        return getStringField("dc.type");
    }
    public void setdctype(String dctype)
    {
        setStringField("dc.type",dctype);
    }


    public String toString() {
        StringBuffer sb = new StringBuffer();
        sb.append("N:"+mN+";");
        Enumeration keys = mFields.keys();
        while (keys.hasMoreElements()) {
            String key = (String) keys.nextElement();
            sb.append(key+":"+mFields.get(key)+";");
        }
        return sb.toString();
    }

}

i used the same handler class you provided

import java.io.*;

import net.rim.device.api.system.Bitmap;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.InputStream;
import net.rim.device.api.ui.component.*;
import net.rim.device.api.ui.container.MainScreen;
import net.rim.device.api.xml.parsers.*;

import org.w3c.dom.*;


import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;

public  class xmlparsermainscreen extends MainScreen{
private static String xmlres = "/xml/xml1.xml";
private RichTextField textOutputField;
public xmlparsermainscreen() throws ParserConfigurationException,
    net.rim.device.api.xml.parsers.ParserConfigurationException, 
    IOException
{
    InputStream inputStream = getClass().getResourceAsStream(xmlres);
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    byte[] buffer = new byte[10000];
    int bytesRead = inputStream.read(buffer);
    while (bytesRead > 0) {
        baos.write(buffer, 0, bytesRead);
        bytesRead = inputStream.read(buffer);
    }
    baos.close();
    String result=baos.toString();
    ByteArrayInputStream bais = 
        new ByteArrayInputStream(result.getBytes());       
    XMLObject[] xmlObjects = getXMLObjects(bais);
    for (int i = 0; i < xmlObjects.length; i++) {
       XMLObject o = xmlObjects[i];
       textOutputField = new RichTextField();
       add(textOutputField);
       textOutputField.setText(o.toString());
       // add(new LabelField(o.toString()));
    }
    LabelField resultdis=new LabelField("resultdisplay");
    add(resultdis);
   //textOutputField = new RichTextField();
    //add(textOutputField);
    //textOutputField.setText(result);
}
static XMLObject[] getXMLObjects(InputStream is) throws 
ParserConfigurationException {
    XMLObjectHandler xmlObjectHandler = new XMLObjectHandler();
        try {
            SAXParser parser = SAXParserFactory.newInstance()
                    .newSAXParser();
            parser.parse(is, xmlObjectHandler);
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    return xmlObjectHandler.getXMLObjects();
    }
}

App code:

import java.io.IOException;
import javax.xml.parsers.ParserConfigurationException;
import net.rim.device.api.ui.UiApplication;
public class xmlparser extends UiApplication {  
private xmlparser() throws ParserConfigurationException, 
    net.rim.device.api.xml.parsers.ParserConfigurationException, 
    IOException 
    {
        pushScreen( new xmlparsermainscreen() );
    }

    public static void main( String[] args ) 
    throws ParserConfigurationException, 
    net.rim.device.api.xml.parsers.ParserConfigurationException, 
    IOException 
    {
        new xmlparser().enterEventDispatcher();
    }
}

the xml i am using

<resultPage xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:foxml="info:fedora/fedora-system:def/foxml#"
xmlns:zs="http://www.loc.gov/zing/srw/" indexName="BasicIndex"
dateTime="Wed Mar 17 09:13:26 ADT 2010">
  <gfindObjects hitTotal="199" resultPageXslt="" hitPageSize="2"
  hitPageStart="1" query="dc.title:&quot;charlottetown&quot;">
    <objects>
      <object no="1" score="4.550192">
        <field name="PID">ilives:86472</field>
        <field name="dc.coverage">Charlottetown (P.E.I.)</field>
        <field name="dc.coverage">Prince Edward Island</field>
        <field name="dc.creator">Hines, Sherman , 1941-</field>
        <field name="dc.format">electronic</field>
        <field name="dc.identifier">None</field>
        <field name="dc.identifier">ilives:86472</field>
        <field name="dc.language">eng</field>
        <field name="dc.publisher">Random House</field>
        <field name="dc.subject">Description--Views</field>
        <field name="dc.subject">Description and
        travel--Views</field>
        <field name="dc.title" snippet="yes">
        <span class="highlight">Charlottetown</span>and Prince
        Edward Island: Sherman Hines images of Canada</field>
        <field name="dc.type">collection</field>
        <field name="dc.type">bib-only</field>
        <field name="fgs.createdDate">
        2009-06-09T18:24:11.972Z</field>
        <field name="fgs.label">191_86472 _foXML.xml</field>
        <field name="fgs.lastModifiedDate">
        2009-06-23T19:29:44.930Z</field>
        <field name="fgs.ownerId">fedoraAdmin</field>
        <field name="fgs.state">Active</field>
        <field name="mods.dateIssued">1990</field>
        <field name="mods.extent">1 v. unpaged ; 22 cm.</field>
        <field name="mods.form">print</field>
        <field name="mods.issuance">monographic</field>
        <field name="mods.place_of_publication">Toronto</field>
        <field name="mods.publisher">Random House</field>
        <field name="mods.subTitle">Sherman Hines images of
        Canada</field>
        <field name="mods.subject">Charlottetown (P.E.I.)</field>
        <field name="mods.subject">Description</field>
        <field name="mods.subject">Views</field>
        <field name="mods.subject">Prince Edward Island</field>
        <field name="mods.subject">Description and travel</field>
        <field name="mods.subject">Views</field>
        <field name="mods.title">Charlottetown and Prince Edward
        Island</field>
        <field name="rels.hasModel">
        info:fedora/ilives:bookCModel</field>
        <field name="rels.isMemberOf">
        info:fedora/ilives:collection</field>
      </object>
    </objects>
  </gfindObjects>
</resultPage>
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

UPDATE updated to skip span and concat values from fields with same name

Hi! I would suggest to use hashtable to handle those "fields":

class XMLObject {
    private Hashtable mFields = new Hashtable();
    private int mN = -1;

    public int getN() {
        return mN;
    }

    public void setN(int n) {
        mN = n;
    }

    public boolean isFieldExist(String key)
    {
        return mFields.containsKey(key);
    }

    public String getStringField(String key) {
        return (String) mFields.get(key);
    }

    public void setStringField(String key, String value) {
        mFields.put(key, value);
    }

    public String getPID() {
        return getStringField("PID");
    }

    public void setPID(String pid) {
        setStringField("PID", pid);
    }

    public String getDcCoverage() {
        return getStringField("dc.coverage");
    }

    public void setDcCoverage(String dcCoverage) {
        setStringField("dc.coverage", dcCoverage);
    }

    public String getFgsOwnerId() {
        return getStringField("fgs.ownerId");
    }

    public void setFgsOwnerId(String fgsOwnerId) {
        setStringField("fgs.ownerId", fgsOwnerId);
    }

    public String dccreator() {
        return getStringField("dc.creator");
    }

    public void dccreator(String dccreator) {
        setStringField("dc.creator", dccreator);
    }

    public String getdcformat() {
        return getStringField("dc.format");
    }

    public void setdcformat(String dcformat) {
        setStringField("dc.format", dcformat);
    }

    public String getdcidentifier() {
        return getStringField("dc.identifier");
    }

    public void setdcidentifier(String dcidentifier) {
        setStringField("dc.identifier", dcidentifier);
    }

    public String getdclanguage() {
        return getStringField("dc.language");
    }

    public void setdclanguage(String dclanguage) {
        setStringField("dc.language", dclanguage);
    }

    public String getdcpublisher() {
        return getStringField("dc.publisher");
    }

    public void setdcpublisher(String dcpublisher) {
        setStringField("dc.publisher", dcpublisher);
    }

    public String getdcsubject() {
        return getStringField("dc.subject");
    }

    public void setdcsubject(String dcsubject) {
        setStringField("dc.subject", dcsubject);
    }

    public String getdctitle() {
        return getStringField("dc.title");
    }

    public void setdctitle(String dctitle) {
        setStringField("dc.title", dctitle);
    }

    public String getdctype() {
        return getStringField("dc.type");
    }

    public void setdctype(String dctype) {
        setStringField("dc.type", dctype);
    }

    public String toString() {
        StringBuffer sb = new StringBuffer();
        sb.append("N:" + mN + ";");
        Enumeration keys = mFields.keys();
        while (keys.hasMoreElements()) {
            String key = (String) keys.nextElement();
            sb.append(key + ":" + mFields.get(key) + ";
");
        }
        return sb.toString();
    }
}

Then in handler you will not have to set some specific class member, just put value using "name" attribute as a key:

class XMLObjectHandler extends DefaultHandler {
    private String mCurrentTag = "";
    private String mCurrentText = "";
    private Attributes mCurrentAttr = null;
    private XMLObject[] mXMLObjects = new XMLObject[] {};
    private XMLObject mCurrentXMLObject = new XMLObject();
    private boolean mIgnoreTag = false;

    public XMLObject[] getXMLObjects() {
        return mXMLObjects;
    }

    public void startElement(String uri, String localName, String name,
            Attributes attributes) throws SAXException {
        mIgnoreTag = mCurrentTag.equalsIgnoreCase("field")
                && name.equalsIgnoreCase("span");

        if (!mIgnoreTag) {
            mCurrentTag = name;
            mCurrentAttr = attributes;
        } else {
            mCurrentText += " ";
        }
        if (mCurrentTag.equalsIgnoreCase("object")) {
            mCurrentXMLObject = new XMLObject();
            mCurrentXMLObject.setN(Integer
                    .parseInt(mCurrentAttr.getValue("no")));
        }
    }

    public void characters(char[] ch, int start, int length)
            throws SAXException {
        if (mCurrentTag.equalsIgnoreCase("field"))
            mCurrentText = mCurrentText.concat(new String(ch, start, length));
    }

    public void endElement(String uri, String localName, String name)
            throws SAXException {
        if (name.equalsIgnoreCase("field")) {
            String fieldName = mCurrentAttr.getValue("name");
            if(mCurrentXMLObject.isFieldExist(fieldName))
            {
                mCurrentText = mCurrentXMLObject.getStringField(fieldName) 
                                + " " + mCurrentText;
            }           
            mCurrentXMLObject.setStringField(fieldName, mCurrentText);
        } else if (name.equalsIgnoreCase("object")) {
            Arrays.add(mXMLObjects, mCurrentXMLObject);
        }
        if (!mIgnoreTag) {
            mCurrentTag = "";
            mCurrentText = "";
        } else {
            mCurrentText += " ";
        }
    }
}

See sample usage:

    public Scr() {
        StringBuffer sb = new StringBuffer();
        sb.append("<Objects>");
        sb.append("<Object no="1">");
        sb
                .append("<field name="PID">ilives:87877</field>"+
            "<field name="dc.coverage">Charlottetown</field>"+
            "<field name="fgs.ownerId">fedoraAdmin</field>");
        sb.append("</Object>");
        sb.append("<Object no="2">");
        sb
                .append("<field name="PID">ilives:87878</field>"+
            "<field name="dc.coverage">Rimston</field>"+
            "<field name="fgs.ownerId">jamesAdmin</field>");
        sb.append("</Object>");
        sb.append("</Objects>");

        String xml = sb.toString();
        ByteArrayInputStream bais = 
            new ByteArrayInputStream(xml.getBytes());       
        XMLObject[] xmlObjects = getXMLObjects(bais);
        for (int i = 0; i < xmlObjects.length; i++) {
            XMLObject o = xmlObjects[i];
            add(new LabelField(o.toString()));
        }
    }

    static XMLObject[] getXMLObjects(InputStream is) {
        XMLObjectHandler xmlObjectHandler = new XMLObjectHandler();
            try {
                SAXParser parser = SAXParserFactory.newInstance()
                        .newSAXParser();
                parser.parse(is, xmlObjectHandler);
            } catch (ParserConfigurationException e) {
                e.printStackTrace();
            } catch (SAXException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        return xmlObjectHandler.getXMLObjects();
    }
}

alt text http://img441.imageshack.us/img441/1372/saxj.jpg

PS If there will be performance issues (say having over 1000 xml objects) just replace hashtable with class members and update handler accordingly...


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...