2

解析xml时遇到问题。xml格式是这样的,

<root>
   <menu>
       <items>
           <menu>
               <items>               
                   <menu>
                       <content/>
                   </menu>
                   <menu>
                       <content/>
                   </menu>
                   <menu>
                       <content/>
                   </menu>
               <items>               
           </menu>
           <menu>
               <items>               
                   <menu>
                       <content/>
                   </menu>
                   <menu>
                       <content/>
                   </menu>
                   <menu>
                      <items>               
                         <menu>
                             <content/>
                         </menu>
                         <menu>
                             <content/>
                         </menu>
                         <menu>
                             <content/>
                         </menu>
                      <items>
                   </menu>
               <items>
           </menu>
       </items>
   </menu>
</root>

我不知道xml有多深......我可以使用两个sax解析器来解析这个xml,我读的是,调用MenuItemParser来解析,而我读的是,调用ItemsParser来解析???

4

2 回答 2

3

是的,可以做到。我假设您使用的是 org.xml.sax 实现(但基本技术应该适用于任何 SAX 类型的解析器)。

使用 SAX 时,您有一个XMLParser执行实际解析的对象,并向它传递一个实现(例如)ContentHandler接口的对象。

如果您想将项目与菜单分开处理,您所做的就是使用两个 ContentHandlers,比如说ItemContentHandlerMenuContentHandler。在每个处理程序中,如果您遇到希望由另一个处理程序处理的内容,您只需告诉它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 行的重复,所以我们再次切换到第MenuContentHandler3 点来检查菜单元素的内容。

下一个元素是第<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 行相同。

希望能解释得更好一点!

于 2011-03-02T03:51:07.133 回答
0

您不需要两个解析器来使用 SAX 来处理这个问题。您只需要在每个标签开始/结束事件中执行正确的操作即可;例如推送或弹出堆栈。

或者,使用 DOM 解析器。

此页面包含指向 SAX 和 DOM 解析器的教程和示例的链接。你最好先看看它们……在你开始编码之前。

于 2011-03-02T03:41:23.147 回答