BlackBerry/J2ME - SAX parse collection of objects with attributes

后端 未结 2 1711
别那么骄傲
别那么骄傲 2020-12-21 21:00

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.

    
        

        
      
      
      
2条回答
  •  北荒
    北荒 (楼主)
    2020-12-21 22:04

    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) + ";\n");
            }
            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("");
            sb.append("");
            sb
                    .append("ilives:87877"+
                "Charlottetown"+
                "fedoraAdmin");
            sb.append("");
            sb.append("");
            sb
                    .append("ilives:87878"+
                "Rimston"+
                "jamesAdmin");
            sb.append("");
            sb.append("");
    
            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...

提交回复
热议问题