是的,可以做到。我假设您使用的是 org.xml.sax 实现(但基本技术应该适用于任何 SAX 类型的解析器)。
使用 SAX 时,您有一个XMLParser
执行实际解析的对象,并向它传递一个实现(例如)ContentHandler
接口的对象。
如果您想将项目与菜单分开处理,您所做的就是使用两个 ContentHandlers
,比如说ItemContentHandler
和MenuContentHandler
。在每个处理程序中,如果您遇到希望由另一个处理程序处理的内容,您只需告诉它XMLReader
使用另一个处理程序。
如果您希望标签中包含的所有内容<menu>
都由 处理MenuContentHandler
,而标签内的所有内容<items>
都由 处理ItemContentHandler
,您可以执行以下操作:
class MenuContentHandler implements ContentHandler
{
public XMLReader reader;
public ItemContentHandler itemHandler;
...
public void startElement(java.lang.String uri, java.lang.String localName,
java.lang.String qName, Attributes atts)
{
if (localName.equals("items"))
reader.setContentHandler(itemHandler); // Point 1
}
...
public void endElement(java.lang.String uri, java.lang.String localName,
java.lang.String qName)
{
if (localName.equals("menu"))
reader.setContentHandler(itemHandler); // Point 2
}
...
}
class ItemContentHandler implements ContentHandler
{
public XMLReader reader;
public MenuContentHandler menuHandler;
...
public void startElement(java.lang.String uri, java.lang.String localName,
java.lang.String qName, Attributes atts)
{
if (localName.equals("menu"))
reader.setContentHandler(menuHandler); // Point 3
}
...
public void endElement(java.lang.String uri, java.lang.String localName,
java.lang.String qName)
{
if (localName.equals("items"))
reader.setContentHandler(menuHandler); // Point 4
}
...
}
...
void doParsing ( )
{
XMLReader reader = XMLReaderFactory.createXMLReader();
MenuContentHandler menuHandler = new MenuContentHandler(reader);
ItemContentHandler itemHandler = new ItemContentHandler(reader);
menuHandler.itemHandler = itemHandler;
itemHandler.menuHandler = menuHandler;
reader.setContentHandler(menuhandler);
reader.parse (/*your document*/);
}
不是世界上最好的代码,但希望它能说明问题……如果您需要更多,请告诉我。
编辑:这是如何工作的 - 想象以下 XML 片段:
1 <menu>
2 <items>
3 <menu>
4 <content/>
5 </menu>
6 <menu>
7 <content/>
8 </menu>
9 <menu>
10 <content/>
11 </menu>
12 </items>
13 </menu>
假设当读者从这个片段开始时,ItemContentHandler
是在控制之中。
它首先遇到的是第<menu>
1 行的标签。这表示菜单项的开始,所以我们切换到MenuContentHandler
(上面标记为“第 3 点”)以便我们可以读取菜单元素的内容。
在这种情况下,元素中的第一个东西实际上是一个 item 元素(第 2 行),因此我们以同样的方式更改为,ItemContentHandler
以便它可以处理 item 元素的内容(这次,在第 1 点)。
第 3 行是第 1 行的重复,所以我们再次切换到第MenuContentHandler
3 点来检查菜单元素的内容。
下一个元素是第<content/>
4 行的标签,它由MenuContentHandler
(我在上一段中提到,目前负责)处理。
在第 5 行,菜单以</menu>
标签关闭。现在,由于所有菜单元素都包含在 item 元素中,我们知道我们现在必须在菜单的包含 item 元素中。因此,我们切换到ItemContentHandler
. 这是第 2 点。
第 6 行开始一个新的菜单项,因此处理方式与第 1 行和第 3 行相同。第 7 行到第 11 行以此类推。
第 12 行结束了 items 元素,通过与第 5、8 和 11 行相同的逻辑,我们知道我们现在必须在包含 item 元素的菜单元素中。所以,我们变成MenuContentHandler
(第4点)。
第 12 行是菜单项的结尾,因此与第 5、8 和 11 行相同。
希望能解释得更好一点!