Question

I just don't want to reinvent the wheel if not necessary so I'll ask you the following, what is the easiest ways to parse the following into a Java date using a saxparser extension?

<start-date>
   <year>2012</year>
   <month>04</month>
   <day>10</day>
</start-date>


if (currentQName.equals("start-date")) {
         //return Java date the easiest way possible.
}

My solution involves saving all three than checking all possibilities and I want to avoid that if possible.

Tricky thing is that there are restriction originating from DTD, only YEAR is mandatory, if month is defined, than day is mandatory as well.

Thanks!

Was it helpful?

Solution

StringBuilder buf = new StringBuilder();
int year;
int month;
int day;

@Override
public void startElement(String uri, String localName, String qName,
        Attributes attributes) throws SAXException {
    if (localName.equals("year")) {
        buf.setLength(0);
    } else if (localName.equals("month")) {
        buf.setLength(0);
    } else if (localName.equals("day")) {
        buf.setLength(0);
    }
}

@Override
public void endElement(String uri, String localName, String qName)
        throws SAXException {
    if (localName.equals("start-date")) {
       doSomethingWith(year,month,day);
    } else if (localName.equals("year")) {
        year = Integer.parseInt(buf.toString());
    } else if (localName.equals("month")) {
        month = Integer.parseInt(buf.toString());
    } else if (localName.equals("day")) {
        day = Integer.parseInt(buf.toString());
    }
}

@Override
public void characters(char chars[], int start, int length)
        throws SAXException {
    buf.append(chars, start, length);
}

OTHER TIPS

The following block will give you a format of YYYY or YYYY/MM or YYYY/MM/DD depending on what your XML looks like and it handles a few error scenarios. You can then turn around and format that into a java.util.Date object or whatever you want to use it for.

Please keep in mind when implementing any SAX filtering/handling that you should always call 'super' for any events you intercept to make sure you are passing the events on to any downstream handler otherwise they'll vanish from the stream and someone will have some trouble debugging at some point.

StringBuilder buf = null;

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

    if ("month".equals(localName) || "day".equals(localName)) {
        if (buf != null) {
            buf.append("/");
        } else {
            throw new SAXException("something went wrong, we received a month and day outside a start-date");
        }
    } else if ("start-date".equals(localName)){
        //there's another error condition that should be handled here if we encounter a start-date but we're already buffering
        buf = new StringBuilder();
    }
    super.startElement(uri,localName,qName);
}

@Override
public void endElement(String uri, String localName, String qName)
        throws SAXException {
    if ("start-date".equals(localName)) {
        //buf will be int he format of YYYY OR YYYY/MM OR YYYY/MM/DD depending on what was in your XML.
        doSomethingWith(buf.toString());
    }
    super.endElement(uri,localName,qName); 
}

@Override
public void characters(char chars[], int start, int length)
        throws SAXException {
    if (buf != null) {
        buf.append(chars, start, length);
    }
    super.characters(chars,start,length);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top