如何实现两个解析器来解析一个xml?

时间:2011-03-02 02:58:22

标签: java android xml saxparser

解析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来解析???

2 个答案:

答案 0 :(得分: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处于控制之中。

它遇到的第一件事就是第1行的<menu>标签。这表示菜单项的开始,所以我们切换到MenuContentHandler(这在上面标记为“Point 3”)所以我们可以读取菜单元素的内容。

在这种情况下,元素中的第一件事实际上是一个item元素(第2行),所以我们以同样的方式更改为ItemContentHandler,以便它可以处理item元素的内容(这时间,在第1点)。

第3行是第1行的重复,所以我们再次切换到第3点的MenuContentHandler来检查菜单元素的内容。

下一个元素是第4行的<content/>标记,由MenuContentHandler处理(我在上一段中提到过,目前正在处理)。

在第5行,菜单以</menu>标记结束。现在,由于所有菜单元素都包含在item元素中,因此我们知道现在必须在菜单中包含item元素。因此,我们切换到ItemContentHandler。这是第2点。

第6行启动一个新的菜单项,因此与第1行和第3行的处理方式相同。对于第7行到第11行,依此类推。

第12行结束items元素,并且通过与第5,8和11行等效的逻辑,我们知道现在必须在包含item元素的menu元素中。所以,我们改为MenuContentHandler(第4点)。

第12行是菜单项的结尾,因此与第5,8和11行的处理方式相同。

希望能更好地解释一下!

答案 1 :(得分:0)

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

或者,使用DOM解析器。

This page包含指向SAX和DOM解析器的教程和示例的链接。在你深入编码之前,你可能最好先看看它们。