Как работает эта Java-программа? - PullRequest
1 голос
/ 04 апреля 2011

Я читал о DOMParser и SAXParser в Java.Я не сомневаюсь в DOMParser, и люди предпочитают SAXParser, а не DOMParser, потому что он занимает память.Однако я понимаю концепцию SAXParser, я не мог под этим кодом:

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class ReadXMLFileSAX {

 public static void main(String args[]) {

  try {

     SAXParserFactory factory = SAXParserFactory.newInstance();
     SAXParser saxParser = factory.newSAXParser();

     DefaultHandler handler = new DefaultHandler() {

     boolean bfname = false;
     boolean blname = false;
     boolean bnname = false;
     boolean bsalary = false;

     public void startElement(String uri, String localName,
        String qName, Attributes attributes)
        throws SAXException {

        System.out.println("Start Element :" + qName);

        if (qName.equalsIgnoreCase("FIRSTNAME")) {
           bfname = true;
        }

        if (qName.equalsIgnoreCase("LASTNAME")) {
           blname = true;
        }

        if (qName.equalsIgnoreCase("NICKNAME")) {
           bnname = true;
        }

        if (qName.equalsIgnoreCase("SALARY")) {
           bsalary = true;
        }

     }

     public void endElement(String uri, String localName,
          String qName)
          throws SAXException {

          System.out.println("End Element :" + qName);

     }

     public void characters(char ch[], int start, int length)
         throws SAXException {

         if (bfname) {
            System.out.println("First Name : "
                + new String(ch, start, length));
            bfname = false;
          }

          if (blname) {
              System.out.println("Last Name : "
                  + new String(ch, start, length));
              blname = false;
           }

          if (bnname) {
              System.out.println("Nick Name : "
                  + new String(ch, start, length));
              bnname = false;
           }

          if (bsalary) {
              System.out.println("Salary : "
                  + new String(ch, start, length));
              bsalary = false;
           }

        }

      };

      saxParser.parse("/home/anto/Groovy/Java/file.xml", handler);

    } catch (Exception e) {
      e.printStackTrace();
    }
  }

}

И файл .xml:

<?xml version="1.0"?>
<company>
    <staff>
        <firstname>yong</firstname>
        <lastname>mook kim</lastname>
        <nickname>mkyong</nickname>
        <salary>100000</salary>
    </staff>
    <staff>
        <firstname>low</firstname>
        <lastname>yin fong</lastname>
        <nickname>fong fong</nickname>
        <salary>200000</salary>
    </staff>
</company>

И когда я запускаю программу я получаювывод выглядит так:

Start Element :company
Start Element :staff
Start Element :firstname
First Name : yong
End Element :firstname
Start Element :lastname
Last Name : mook kim
End Element :lastname
Start Element :nickname
Nick Name : mkyong
End Element :nickname
Start Element :salary
Salary : 100000
End Element :salary
End Element :staff
Start Element :staff
Start Element :firstname
First Name : low
End Element :firstname
Start Element :lastname
Last Name : yin fong
End Element :lastname
Start Element :nickname
Nick Name : fong fong
End Element :nickname
Start Element :salary
Salary : 200000
End Element :salary
End Element :staff
End Element :company

Вывод выглядит очень хорошо, но я запутался с выводом!Как распечатывается порядок вывода?Который обрабатывает это?Так как я впервые прочитал SAX и DOM, я не смог понять это, пожалуйста, помогите мне.

Ответы [ 7 ]

2 голосов
/ 04 апреля 2011

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

Таким образом, поток здесь:

  1. См. Тег company, позвоните startElement для этого
  2. См. Тег staff, позвоните startElement для этого
  3. См. Тег firstname, для этого вызовите startElement (который устанавливает логическое значение)
  4. См. Символы ("yong"), вызвать для них функцию characters (которая определяет, какой логический тип установлен, печатает соответствующее сообщение и очищает флаг)
  5. См. Закрывающий тег firstname, вызовите функцию endElement

...

2 голосов
/ 04 апреля 2011

Вызывая saxParser.parse("/home/anto/Groovy/Java/file.xml", handler);, SAX Parser использует ваш DefaultHandler (то есть ваш handler, который вы передали в качестве параметра), который вы реализовали для анализа XML.

SAX основан на событиях, эти события встречаются, когда анализатор перемещается в вашем XML-документе. Когда парсер SAX встречает начало элемента, например <firstname>, он вызывает метод startElement. Затем, перейдите к телу элемента start и увидите yong. Поскольку он не заключен в тег <>, он считается текстовым узлом, поэтому он вызывает метод characters. Если бы был другой элемент XML, он снова вызвал бы startElement для нового элемента XML.

Наконец, SAX Parser обходит, пока не увидит конечный элемент </firstname> и не вызовет метод endElement.

Все эти 3 метода startElement, characters и endElement реализованы разработчиком (в вашем случае, ВЫ).

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

Надеюсь, это поможет!

0 голосов
/ 04 апреля 2011

В конце вы заметите, что в качестве параметра saxParser.parse() указан handler. Обработчик является экземпляром DefaultHandler, который был определен ранее в коде. SAXParser вызывает соответствующий метод в обработчике, когда он анализирует XML-документ. Вот некоторые Javadoc для DefaultHandler и SAXParser (см. Документацию по методам parse). Поскольку документ XML анализируется и каждый метод в обработчике вызывается по очереди, метод обработчика печатает значения, которые были обработаны.

0 голосов
/ 04 апреля 2011

SAX-парсер просто перебирает документ по одному символу за раз.Метод parse() Parser принимает объект Handler.Различные методы этого объекта вызываются синтаксическим анализатором, когда анализатор встречает определенные символы в документе («событие»).Поэтому каждый раз, когда синтаксический анализатор встречает начальный тег, он вызывает метод обработчика startElement, когда он встречает конечный тег, он вызывает метод endElement и так далее.Эти методы в DefaultHandler пусты.Вы сами можете создать подкласс этого класса и предоставить собственную реализацию этих методов (в приведенном выше примере кода обработчик по умолчанию анонимно разделен на подклассы).

В отличие от анализатора DOM анализатор SAX не создает элементы- он просто запускает различные методы-обработчики, так как встречает начальные и конечные теги и символы содержимого.В этих методах вы должны предоставить логику, которая отображает конечный тег на начальный тег и т. Д., Что и делают операторы условия в методах startElement и endElement.А переменные класса blname и т. Д. Просто отслеживают, в каком элементе в данный момент находится синтаксический анализатор, чтобы вы знали, к чему относятся символы, которые передаются в метод characters().

0 голосов
/ 04 апреля 2011

Когда синтаксический анализатор читает входной XML, он вызывает startElement для каждого открывающего тега и endElement для каждого закрывающего тега. Если анализатор встречает содержимое тега, например yong, он вызывает characters.

Код, который вы опубликовали, отслеживает, какой тег анализируется в данный момент, используя переменные состояния bfname, bsalary и т. Д. После вызова characters ваш код знает, для какого объекта он вызывается - имя, фамилия или зарплата , поэтому он может правильно расшифровать строку необработанных символов.

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

Напротив, при использовании анализатора DOM вы преобразуете весь XML-документ в дерево, поэтому вы можете перемещаться от его корня к узлам или назад - от узлов к корню любым удобным для вас способом.

0 голосов
/ 04 апреля 2011

Заказ выглядит хорошо для меня. В чем проблема?

Если вы говорите о начальном и конечном элементах, это просто показывает вложение XML-тега. Вы видите, что «компания» предшествует «персоналу», а «персонал» - «имени».

Наконец, у вас есть сами данные внутри отдельных тегов. Вот почему последние три строки:

End Element :salary
End Element :staff
End Element :company

Поскольку зарплата уходит, зарплата - это последний элемент персонала, а это конечный персонал компании.

0 голосов
/ 04 апреля 2011

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

...