xml - Java SAX Parsing -
there's xml stream need parse. since need once , build java objects, sax looks natural choice. i'm extending defaulthandler , implementing startelement, endelement , characters methods, having members in class save current read value (taken in characters method).
i have no problem doing need, code got quite complex , i'm sure there's no reason , can things differently. structure of xml this:
<players> <player> <id></id> <name></name> <teams total="2"> <team> <id></id> <name></name> <start-date> <year>2009</year> <month>9</month> </start-date> <is-current>true</is-current> </team> <team> <id></id> <name></name> <start-date> <year>2007</year> <month>11</month> </start-date> <end-date> <year>2009</year> <month>7</month> </end-date> </team> </teams> </player> </players>
my problem started when realized same tag names used in several areas of file. example, id , name exist both player , team. want create instances of java classes player , team. while parsing, kept boolean flags telling me whether i'm in teams section in endelement know name team's name, not player's name , on.
here's how code looks like:
public class myparser extends defaulthandler { private string currentvalue; private boolean inteamssection = false; private player player; private team team; private list<team> teams; public void characters(char[] ch, int start, int length) throws saxexception { currentvalue = new string(ch, start, length); } public void startelement(string uri, string localname, string name, attributes attributes) throws saxexception { if(name.equals("player")){ player = new player(); } if (name.equals("teams")) { inteamssection = true; teams = new arraylist<team>(); } if (name.equals("team")){ team = new team(); } } public void endelement(string uri, string localname, string name) throws saxexception { if (name.equals("id")) { if(inteamssection){ team.setid(currentvalue); } else{ player.setid(currentvalue); } } if (name.equals("name")){ if(inteamssection){ team.setname(currentvalue); } else{ player.setname(currentvalue); } } if (name.equals("team")){ teams.add(team); } if (name.equals("teams")){ player.setteams(teams); inteamssection = false; } } }
since in real scenario have more nodes player in addition teams , nodes have tags name , id, found myself messed several booleans similar inteamssection , endelement method becomes long , complex many conditions.
what should differently? how can know name tag, instance, belongs to?
thanks!
there 1 neat trick when writing sax parser: allowed change contenthandler
of xmlreader while parsing. allows separate parsing logic different elements multiple classes, makes parsing more modular , reusable. when 1 handler sees end element switches parent. how many handlers implement left you. code this:
public class roothandler extends defaulthandler { private xmlreader reader; private list<team> teams; public roothandler(xmlreader reader) { this.reader = reader; this.teams = new linkedlist<team>(); } public void startelement(string uri, string localname, string name, attributes attributes) throws saxexception { if (name.equals("team")) { // switch handler parse team element reader.setcontenthandler(new teamhandler(reader, this)); } } } public class teamhandler extends defaulthandler { private xmlreader reader; private roothandler parent; private team team; private stringbuilder content; public teamhandler(xmlreader reader, roothandler parent) { this.reader = reader; this.parent = parent; this.content = new stringbuilder(); this.team = new team(); } // characters can called multiple times per element aggregate content in stringbuilder public void characters(char[] ch, int start, int length) throws saxexception { content.append(ch, start, length); } public void startelement(string uri, string localname, string name, attributes attributes) throws saxexception { content.setlength(0); } public void endelement(string uri, string localname, string name) throws saxexception { if (name.equals("name")) { team.setname(content.tostring()); } else if (name.equals("team")) { parent.addteam(team); // switch handler our parent reader.setcontenthandler(parent); } } }
Comments
Post a Comment