您所描述的问题听起来并不那么难:如果您可以安全地假设 books 元素的每个子元素都是一个“项目”,那么您可以调用您的“项目”处理程序”为每个孩子。
假设 始终是并且仅是文档的顶级元素,以下是(我认为)可行的伪代码:
class BookHandler extends DefaultHandler {
public void startElement(String namespaceURI, String localName,
String qName, Attributes atts) {
if (localName.equals("books") {
// Don't need to do anything with the top level element
return;
}
else {
handleItem(namespaceURI, localName, qName, atts);
}
}
public void endElement(String namespaceURI, String localName, String qName) {
if localName.equals("books") {
// Stop parsing and exit.
}
else {
// Stop parsing one item
}
}
private void handleItem(String namespaceURI, String localName,
String qName, Attributes atts) {
// Handle one item, including handling the "name" and
// "type" child attributes
if (localName.equals("name") {
// handle the name
}
else if (localName.equals("type") {
// handle the type
}
}
}
即使是伪代码,也过于简单和丑陋。另一种方法(但可能对您的需求过于夸张)是将您的应用程序分解为多个 ContentHandler 类,在您到达某些元素的开头或结尾时转移责任。
例如:假设 BookHandler 的一个实例被传递给 parser.parse() 调用,以处理顶级元素。那么:
class BookHandler extends DefaultHandler {
private ContentHandler m_parentHandler;
private ContentHandler m_childHandler = null;
// ... == appropriate args for the DefaultHandler constructor
public BookHandler(ContentHandler parent, Attributes atts, ...) {
super(...);
m_parentHandler = parent;
parent.getXMLReader().setHandler(this);
}
public void startElement(String namespaceURI, String localName,
String qName, Attributes atts) {
if (localName.equals("books") {
// Don't need to do anything with the top level element
return;
}
else {
// Assume it's a new item element. (Note: ItemHandler's constructor
// changes the parser's ContentHandler.)
m_childHandler = new ItemHandler(this, atts, ...);
}
}
public void endElement(String namespaceURI, String localName, String qName) {
if localName.equals("books") {
// Stop parsing and exit.
}
else {
// Note that this won't be called for "item" elements, UNLESS the
// ItemHandler's endElement method explicitly invokes this method.
// Stop parsing one item
}
}
}
class ItemHandler extends DefaultHandler {
private ContentHandler m_parentHandler;
// ItemInfo is a class that holds all info about the current item
private ItemInfo m_ItemInfo = null;
// ... == appropriate args for the DefaultHandler constructor
public ItemHandler(ContentHandler parent, Attributes atts, ...) {
super(...);
m_parentHandler = parent;
m_ItemInfo = new ItemInfo(atts);
parent.getXMLReader().setHandler(this);
}
public void startElement(String namespaceURI, String localName,
String qName, Attributes atts) {
if (localName.equals("name") {
// Handle the name. Update the current item as needed.
}
else if (localName.equals("type") {
// Handle the type. Update the current item as needed.
}
}
public void endElement(String namespaceURI, String localName, String qName) {
if localName.equals("name" || localName.equals("type") {
// Do nothing (?)
}
else {
// Stop parsing the current item;
// let the parent class handle the next element.
getXMLReader().setHandler(m_parentHandler);
// OPTIONALLY -- depending on your app's needs -- call the
// parent's endElement() method to let it know that we reached
// the end of an item.
m_parentHandler.endElement(namespaceURI, localName, qName);
}
}
}
这种方案提供了更大的灵活性,以及更多的重用可能性。例如,“books”元素现在可能是某个其他元素(例如“departments”)的子元素,而无需对这些类进行太多更改。
伪代码无论如何都不是完美的。 (一方面,我想更多地考虑关闭处理程序的位置 - 在父类或子类中。另一方面,我可能在保存对父类和子类的引用方面做得过火了这些课程。)但我希望它能给你一些可以开始工作的想法。