0

I have an XML file and I hant to get the data from it by using SAX. It goes till startElement() where it gets an error because when I try to get the attributes value, these are null. Why?

First of all, I call this method: load()

public RealEstate load() {
        RealEstate data = null; 
        try {     
            //Create a "parser factory" for creating SAX parsers
            SAXParserFactory spfac = SAXParserFactory.newInstance();

            //Now use the parser factory to create a SAXParser object
            SAXParser sp = spfac.newSAXParser();
            XMLReader xmlReader = sp.getXMLReader(); 

            //Create an instance of this class; it defines all the handler methods
            SaxParserRealEstateHandler handler = new SaxParserRealEstateHandler();

            //assign our handler
            xmlReader.setContentHandler(handler);

            // Convert file to URL.
            URL url = handler.fileToURL(new File(xmlFilename));

            // Parse file.
            xmlReader.parse(url.toString()); 

            data = handler.getData();

        } catch (ParserConfigurationException ex) {
            Logger.getLogger(RealStatePersistXML.class.getName()).log(Level.SEVERE, null, ex);
        } 
        catch (SAXException ex) {
            Logger.getLogger(RealStatePersistXML.class.getName()).log(Level.SEVERE, null, ex);
        }
        catch (IOException ex) {
           Logger.getLogger(RealStatePersistXML.class.getName()).log(Level.SEVERE, null, ex);
       }
        return data;
    }

Here I have the methods startElement and endElement.

    class SaxParserRealEstateHandler extends DefaultHandler
    {

        private String temp;
        private RealEstate data;
        private Estate estate;
        private estateAddress address;

        /**
         * CONSTRUCTOR
         */
        public SaxParserRealEstateHandler() 
        {
        }


        /**
         * getData()
         * This method gets the list of estates from RealEstate class.
         * @return data list of states. Null in case of error or list not found.
         */
        public RealEstate getData()
        {
        //    RealEstate data = new RealEstate();
           // data.addEstate(estate);
           // data.getEstates();
        //    return data;
        }

        /*
        * When the parser encounters plain text (not XML elements),
        * it calls(this method, which accumulates them in a string buffer
        */
       public void characters(char[] buffer, int start, int length) {
            temp = new String(buffer, start, length);
       }


        /*
        * Every time the parser encounters the beginning of a new element,
        * it calls this method, which resets the string buffer
        */ 
        public void startElement(String uri, String localName, String qName, Attributes attributes){ 

            switch (qName){     
                case"realState":
                    data = new RealEstate();
                    break;
                case"estate":
                    estate = new Estate();
                    estate.setType(attributes.getValue("type"));
                    estate.setSurface(Double.parseDouble(attributes.getValue("surface")));
                    //estate.setAddress(attributes.getValue("address"));
                    estate.setPrice(Integer.parseInt(attributes.getValue("price"))); 
                    break;     
                case"address":
                    address = new estateAddress();
                    address.setStreet(attributes.getValue("type"));
                    address.setNumber(Integer.parseInt(attributes.getValue("surface")));
                    address.setFloor(Integer.parseInt(attributes.getValue("type")));
                    address.setDoor(Integer.parseInt(attributes.getValue("surface")));
                    break;
                default:
                    break;
            }
        }



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

    switch (qName){
        case"estate": 
            data.getEstates().add(estate);//quant ha llegit la etiqueta (</estate>) l'agreguem
            break; 
        case"surface":
            double surface = Double.parseDouble(temp);
            estate.setSurface(surface);
            break;  
        case"price":
            double price = Double.parseDouble(temp);//tractar tema errors del parseDouble!
            estate.setPrice(price);
            break;    
        case"address":                    
            estate.setAddress(address);
            break;      
        case"street": 
            address.setStreet(temp);
            break;
        case"number":
            int number = Integer.parseInt(temp);
            address.setNumber(number);
            break;
        case"floor":
            address.setStreet(temp);
            break;  
        case"door":
            address.setStreet(temp);
            break;   
        default:
            break;
    }
} 



/** fileToURL()
 * Convenience method to convert a file to a url
 * @throws Error if malformed url exception is generated
 */

    public URL fileToURL(File file) 
{
    String path = file.getAbsolutePath();
    String fSep = System.getProperty("file.separator");
    if (fSep != null && fSep.length() == 1)
        path = path.replace(fSep.charAt(0), '/');
    if (path.length() > 0 && path.charAt(0) != '/')
        path = '/' + path;
    try  
    {
        return new URL("file", null, path);
    }
    catch (java.net.MalformedURLException e) 
    {
        throw new Error("Unexpected MalformedURLException");//no he pogut muntar una url com deu mana
        //retornar null
    }
}
    }

XML code

<?xml version="1.0" encoding="UTF-8"?>
<realState xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="realState.xsd">
    <estate>
        <type>House</type>
        <surface>250,0</surface>
        <address>
            <street>C/Tarragona</street>
            <number>54</number>
            <floor>2</floor>
            <door>1</door>
        </address>
        <price>140000,0</price>
    </estate>
</realState>

XSD code: http://pastebin.com/nzEDsdLg

Classes RealEstate and Estate are working ok!

Thank you!

1 Answer 1

1

type, surface, and price are not attributes of the <estate> element. They are sub-elements.

To be attributes, you XML would be:

<estate type="House" surface="250,0" price="140000,0">
    <address>
        <street>C/Tarragona</street>
        <number>54</number>
        <floor>2</floor>
        <door>1</door>
    </address>
</estate>

Using a StAX parser is a lot easier than a SAX parser, and has very similar performance characteristics, so I suggest you use that instead.

Sign up to request clarification or add additional context in comments.

5 Comments

And what I need to change if I don't want to change the XML code?
Drop the setType(attributes.getValue("type")) call. I mean, you already did write the code necessary to set the value in the endElement() method, so right now you're trying to set the value twice.
ok! I've already deleted it, but now the program finishes without runing the endElement method.
If you add the @Override annotation to the methods, as you should and as any good IDE would tell you to do, you'd get compile error telling you that your endElement() does not in fact override the superclass method, as you intended. That is because it doesn't have an Attributes parameter.
Thank you. When I removed the Attributes param from endElement() it solved the problem.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.