2009-09-18 2 views
0

Это сомнение в SAX. Я хочу обработать теги детей в XML-файле, только если он соответствует родительскому тегу. Для Ex:
Прыжки между XML-тегами

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

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

+0

Пожалуйста, исправьте свой XML, это неверно. –

ответ

1

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

В общем, при разборе 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

@chen: Это все равно потребует прохождения всего xml-файла, не так ли? Могу ли я искать и сопоставлять родительский тег и обрабатывать дочерний тег только в случае совпадения? – fixxxer

+0

Ну. Как только вы начинаете Sax, он готов отсканировать весь документ. Однако, если вы поместите коды в любой из примеров, которые я вам предоставил, они будут запущены после того, как выполнение коснется ваших кодов. Другими словами, к тому времени, когда ваш сакс закончится, все, что вы хотите, чтобы ваши коды делали, уже сделано. –

+0

Okay.So SAX не дает возможности перейти к тегам, не так ли? – fixxxer

0

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

1

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

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

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

0

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

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

+0

На самом деле это файл длиной в 200 строк длиной. И поскольку любой парсер должен будет пройти через него по крайней мере один раз, и мне просто нужно сопоставить один дочерний тег и получить его атрибут, я думаю, что продолжу SAX. Спасибо, что ушли! – fixxxer

1

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

Прецедент для стека при разборе XML

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

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

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

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

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

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

Когда использовать DOM, как Apis

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

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

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

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

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

+0

Это было полезно, но я думаю, мне не нужно ничего сохранять и поэтому намереваюсь продвигать парсер SAX. Спасибо, что ушли. – fixxxer

Смежные вопросы