Переход между тегами XML - PullRequest
       26

Переход между тегами XML

0 голосов
/ 18 сентября 2009

Это сомнение в SAX. Я хочу обработать дочерние теги в XML-файле, только если он соответствует родительскому тегу. Например:

<version>
    <parent tag-1>
       <tag 1>
       <tag 2>
     </parent tag-1 >
     <parent tag-2>
       <tag 1>
       <tag 2>
     </parent tag-2>
</version>

В приведенном выше коде я хочу сначала сопоставить родительский тег (т. Е. Родительский тег-1 или родительский тег``-2, основываясь на пользовательском вводе), и только затем обрабатывать дочерние теги под ним. Можно ли это сделать в SAX-парсере, учитывая, что SAX имеет ограниченный контроль над DOM и что я новичок в SAX и Java? Если да, не могли бы вы привести соответствующий метод? ТИА

Ответы [ 5 ]

1 голос
/ 18 сентября 2009

Решение, предложенное @Wing C. Chen, более чем прилично, но в вашем случае я бы не использовал стек.

Вариант использования стека при разборе XML

Обычный вариант использования стека и XML, например, заключается в проверке сбалансированности тегов XML при использовании вашего собственного лексера (то есть парсера XML, созданного вручную с допустимой ошибкой).

Конкретным примером этого будет построение схемы документа XML для Eclipse IDE.

Когда использовать SAX, парсеры Pull и т.п.

  • Эффективность памяти при разборе огромного файла XML

  • Вам не нужно перемещаться вперед и назад в документе.

Однако использование SAX для анализа сложных документов может стать утомительным, особенно если вы хотите применить операции к узлам на основе некоторых условий.

Когда использовать DOM, например APis

  • Вы хотите легкий доступ к узлам

  • Вы хотите перемещаться вперед и назад в документе в любое время

  • Скорость не является основным требованием против времени разработки / читаемости / обслуживания

Моя рекомендация

Если у вас нет огромного XML, используйте DOM-подобный API и выберите узлы с помощью XPath. Я лично предпочитаю Dom4J, но я не против других APis, таких как JDom или даже Xpp3, которые поддерживают XPath.

1 голос
/ 18 сентября 2009

SAX в любом случае будет спулировать весь документ, если вы хотите сделать это из соображений производительности.

Однако, с точки зрения правильности кода, вы могли бы заставить парсер SAX не возвращать несовпадающие дочерние элементы, связав его с XMLFilter . Возможно, вам все равно придется написать логику самостоятельно - что-то вроде того, что приведено в посте Wing C. Chen - но вместо того, чтобы поместить ее в логику приложения, вы можете абстрагировать ее в реализацию фильтра.

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

1 голос
/ 18 сентября 2009

Конечно, это легко сделать, запомнив родительский тег.

Как правило, при разборе тегов xml люди используют стек для отслеживания карты семейства этих тегов. Ваш случай может быть легко решен с помощью следующего кода:

Stack<Tag> tagStack = new Stack<Tag>();

public void startElement(String uri, String localName, String qName,
        Attributes attributes)
     if(localName.toLowerCase().equals("parent")){
          tagStack.push(new ParentTag());
     }else if(localName.toLowerCase().equals("tag")){
          if(tagStack.peek() instanceof ParentTag){
               //do your things here only when the parent tag is "parent"
          }
     }
}
public void endElement(String uri, String localName, String qName)
        throws SAXException{
     if(localName.toLowerCase().equals("parent")){
          tagStack.pop();
     }
}

Или вы можете просто вспомнить, в каком тэге вы находитесь, обновив тэг:

String tagName = null;
public void startElement(String uri, String localName, String qName,
        Attributes attributes)
     if(localName.toLowerCase().equals("parent")){
          tagName = "parent";
     }else if(localName.toLowerCase().equals("tag")){
          if(tagName!= null && tagName.equals("parent")){
               //do your things here only when the parent tag is "parent"
          }
     }
}
public void endElement(String uri, String localName, String qName)
        throws SAXException{
     tagName = null;
}

Но я предпочитаю стековый способ, потому что он отслеживает все ваши теги предков.

0 голосов
/ 18 сентября 2009

Если вы хотите перейти к определенным тегам, вам нужно использовать парсер DOM. При этом весь документ будет считан в память, а затем предоставлены различные способы доступа к конкретным узлам дерева, например, запрос тега по имени и запрос дочерних элементов этого тега.

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

0 голосов
/ 18 сентября 2009

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

...