开发者

How to implements two parser to parse one xml?

I have a problem when I parse the xml. The xml format is like this,

<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>

I do not 开发者_开发百科know how deep about the xml...... Can I use two sax parser to parse this xml while I read is , call the MenuItemParser to parse, while I read is , call the ItemsParser to parse???


Yep, it can be done. I'll assume you're using the org.xml.sax implementation (but the basic technique should work with any SAX-type parser).

When using SAX you have an XMLParser that performs the actual parsing, and you pass to it an object implementing (for example) the ContentHandler interface.

If you want to handle the items separately to the menus, what you do is use two ContentHandlers, say ItemContentHandler and MenuContentHandler. In each handler, if you run into content you want handled by the other handler, you simply tell the XMLReader to use the other handler instead.

If you want everything contained in <menu> tags to be handled by the MenuContentHandler, and everything inside <items> tags to be handled by the ItemContentHandler, you would do something like the following:

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*/);
}

Not the best code in the world, but hopefully it gets the point across... If you need more, just let me know.

EDIT: how this works - imagine the following snippet of 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>

Assume that when the reader starts with this snippet, the ItemContentHandler is in control.

The first thing it encounters is the <menu> tag on line 1. This indicates the start of a menu item, so we switch to the MenuContentHandler (this is marked "Point 3" above) so that we can read the contents of the menu element.

In this case, the first thing in the element is actually an item element (line 2), so in the same way we change to the ItemContentHandler so that it can handle the contents of the item element (this time, at point 1).

Line 3 is a repeat of line 1, so again we switch to the MenuContentHandler at point 3 to examine the content of the menu element.

The next element is the <content/> tag on line 4, which is handled by the MenuContentHandler (which, I mentioned in the last paragraph, is currently in charge).

On line 5, the menu closes with a </menu> tag. Now, since all the menu elements are contained within item elements, we know that we must now be in the menu's containing item element. Therefore, we switch to the ItemContentHandler. This is point 2.

Line 6 starts a new menu item, and so is treated the same way as lines 1 and 3. And so on for lines 7 through 11.

Line 12 ends the items element, and by the equivalent logic as for lines 5, 8 and 11, we know that we must now be in the menu element that contains the item element. So, we change into the MenuContentHandler (point 4).

Line 12 is the end of a menu item, and so is treated the same as lines 5, 8 and 11.

Hope that explains it a bit better!


You don't need two parsers to handle this using SAX. You just need to do the correct actions at each tag start / end event; e.g. push or pop a stack.

Alternatively, use a DOM parser.

This page has links to tutorials and examples of both SAX and DOM parsers. You'd probably be best off looking at them ... before you dive into coding.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜