【发布时间】:2012-01-25 23:36:53
【问题描述】:
我需要解析一个 XML 流。由于我只需要执行一次并构建我的 java 对象,因此 SAX 看起来是自然的选择。我正在扩展 DefaultHandler 并实现 startElement、endElement 和 characters 方法,在我的类中有成员,我保存当前读取值(在 characters 方法中获取)。
我做我需要的事情没有问题,但我的代码变得相当复杂,我确信没有理由这样做,我可以做不同的事情。 我的 XML 的结构是这样的:
<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>
当我意识到文件的多个区域使用了相同的标签名称时,我的问题就开始了。例如,球员和球队都存在 id 和 name。我想创建我的 java 类 Player 和 Team 的实例。在解析时,我保留了布尔标志,告诉我我是否在团队部分,以便在 endElement 中我会知道该名称是团队的名称,而不是玩家的名称等等。
我的代码如下所示:
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;
}
}
}
因为在我的真实场景中,除了球队之外,我还有更多的节点给玩家,并且这些节点也有名称和 ID 等标签,我发现自己搞砸了几个类似于 inTeamsSection 的布尔值,并且我的 endElement 方法变得很长并且复杂的条件很多。
我应该做些什么不同的事情?例如,我如何知道名称标签属于什么?
谢谢!
【问题讨论】:
-
我会说使用 SAX 是大约 7 年前的自然选择。目前自然的选择是使用 JAXB(或 Xtream,或 XmlBeans 或 JibX)
-
有时您只需要手动进行解析。当您处理兆字节的 XML 时,将其转换为 Java 对象并不是一个好主意。
-
@ʘleg - 如果您使用 JAXB 从 StAX XMLStreamReader 解组对象,您可以解组较大文档的子部分以管理内存限制。
-
'subsections' 表示子树,还是 XML 的一部分?如果有像
这样的普通(单级)XML,是否可以将它们一一解组,而不是完全使用 JAXB?