views:

42

answers:

1

Hello everyone,

I am parsing an XML document. I have done this thousands of times before, but I can't see why I am getting the following issue:

Here is the relevant part of the XML document that I am parsing:

XML: <?xml version="1.0" standalone="yes"?>
<ratings>
<url_template>http://api.netflix.com/users/T1BlCJtdcWMuF6gJEfue96_W.kZ_gW81h59KqLEfT1AzE-/ratings/title?{-join|&amp;amp;|title_refs}&lt;/url_template&gt;
<ratings_item>
    <user_rating value="not_interested"></user_rating>
    <predicted_rating>4.8</predicted_rating>
    <id>http://api.netflix.com/users/T1BlCJtdcWMuF6gJEfue96_W.kZ_gW81h59KqLEfT1AzE-/ratings/title/70112530&lt;/id&gt;
    <link href="http://api.netflix.com/catalog/titles/series/70112530/seasons/70112530" rel="http://schemas.netflix.com/catalog/title" title="Castle: Season 1">
    </link>
    .
    .
    .

So, I am trying to pase out the user_rating, the predicted_rating, and the id. I am doing this successfully. However, I am noticing that when user_rating contains no value, then the predicted_rating will automatically take the value of , rather than it's own value of 4.8. When user_rating does have value, however, then the predicted_rating will have the correct value. Here is my parsing code:

public class RatingsHandler extends DefaultHandler {

Vector vector;
Ratings ratings;

boolean inUserRating;
boolean inPredictedRating;
boolean inAverageRating;
boolean inID;

public void startDocument() throws SAXException {
    vector = new Vector();
    ratings = new Ratings();
}

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

    if (localName.equals("user_rating")) {
        inUserRating = true;

    } else if (localName.equals("predicted_rating")) {
        inPredictedRating = true;

    } else if (localName.equals("average_rating")) {
        inAverageRating = true;

    } else if (localName.equals("id")) {
        inID = true;

    }

}

public void characters(char ch[], int start, int length)
        throws SAXException {

    if (inUserRating) {
        ratings.setUserRating(new String(ch, start, length));
        inUserRating = false;
    } else if (inPredictedRating) {
        ratings.setPredRating(new String(ch, start, length));
        inPredictedRating = false;
    } else if (inAverageRating) {
        ratings.setAvgRating(new String(ch, start, length));
        inAverageRating = false;
    } else if (inID) {
        Const.rating_id = new String(ch, start, length);
        inID = false;
    }
}

public void endDocument() throws SAXException {

    if (ratings != null) {
        vector.addElement(ratings);
    }
}

public Vector getRatings() {
    return vector;
}

 }

Does it have something to do with the fact that user_rating has an attribute "value"? I would appreciate any help. Thanks!

+3  A: 

I would suggest you to wait for the

endElement(String uri, String localName, String qName)

before you mark the element as passed by:

inSomething = false

I can imagine that when the element is empty, the

public void characters(char[] ch, int start, int length)

won't be called, your flag won't be cleared and you will run into inconsitent state having two inSomething flags set to true.

merxbj
that did the trick, thanks a lot!
behrk2
@behrk2: You are welcome! :)
merxbj
Should I be setting all of my boolean values to false in endElement()? I have been doing it all in characters() as shown in the original example above...I fixed the once causing me a problem as you suggested, but I have a lot of other boolean values in other classes that I am setting to false in characters()...
behrk2
Hmm, it depends on the sitution. In the case you have posted, your booleans facticaly indicates that you have already parsed the element. It is reasonable that you can be sure about that only when you hit the end element. However, if you for example want to set some boolean indicating that the element has non-empty value then it makes sense to set it inside the characteds() handler. Hope this helps :)
merxbj