Как реализовать два парсера для разбора одного xml? - PullRequest
2 голосов
/ 02 марта 2011

У меня проблема при разборе 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 ...... Могу ли я использовать два синтаксических анализатора саксофона, чтобы проанализировать этот xml, пока я читаю, вызвать MenuItemParser для анализа, а я прочитал, вызвать ItemsParser для анализа ???

Ответы [ 2 ]

3 голосов
/ 02 марта 2011

Да, это можно сделать.Я предполагаю, что вы используете реализацию org.xml.sax (но базовый метод должен работать с любым парсером SAX-типа).

При использовании SAX у вас есть XMLParser, который выполняет фактический анализи вы передаете ему объект, реализующий (например) интерфейс ContentHandler.

Если вы хотите обрабатывать элементы отдельно от меню, вы используете two 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), так же, как мы меняем тo 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.

Надеюсь, это объясняет это немного лучше!

0 голосов
/ 02 марта 2011

Вам не нужны два парсера для обработки этого с использованием SAX.Вам просто нужно делать правильные действия при каждом событии начала / конца тега;например, нажмите или вытолкните стек.

В качестве альтернативы используйте анализатор DOM.

Эта страница содержит ссылки на учебные пособия и примеры как синтаксических анализаторов SAX, так и DOM.Вам, вероятно, лучше посмотреть на них ... прежде чем погрузиться в кодирование.

...