Как парсинг XML работает внутри SAX Parser? - PullRequest
0 голосов
/ 10 марта 2019

Я пытаюсь разобрать XML с помощью SAX. Ниже приведен фрагмент кода:

public class ReadXML {

   public static void main(String argv[]) {

    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("Parameters :" + uri +":"+ localName +":"+ qName +":"+ attributes);
        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 {

        System.out.println("Im here:"+Arrays.toString(ch));
        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("C:\\Lenny\\Work\\XML\\SaxParsing_01.xml", handler); --(1)


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

   }

}

Мой первый вопрос: когда код достигает значения saxParser.parse("C:\\Ashish\\Work\\XML\\SaxParsing_01.xml", handler);, ниже вызывается два метода ..!

    public void parse(File f, HandlerBase hb)
            throws SAXException, IOException {
            if (f == null) {
                throw new IllegalArgumentException("File cannot be null");
            }

            String escapedURI = FilePathToURI.filepath2URI(f.getAbsolutePath());
            if (DEBUG) {
                System.out.println("Escaped URI = " + escapedURI);
            }
            InputSource input = new InputSource(escapedURI);
            this.parse(input, hb);
        }

public void parse(InputSource is, DefaultHandler dh)
        throws SAXException, IOException {
        if (is == null) {
            throw new IllegalArgumentException("InputSource cannot be null");
        }
        XMLReader reader = this.getXMLReader();
        if (dh != null) {
            reader.setContentHandler(dh);
            reader.setEntityResolver(dh);
            reader.setErrorHandler(dh);
            reader.setDTDHandler(dh);
        }
        reader.parse(is);
    }

Интересно узнать, что происходит внутри, когда вызывается reader.parse(is)? Единственное, что я предполагаю, это то, что reader читает XML и помещает его в структуру данных DefautHandler, созданную в вышеприведенном коде, и производит соответствующий вывод.

Я много раз пытался выяснить исходный код метода parse(is), но не смог его найти. В классе SAXParser синтаксический анализ - это абстрактный метод, поэтому я не смог найти класс реализации, где я мог бы проверить исходный код и понять его дальше.

Второй, но глупый вопрос, могу ли я знать, пожалуйста, когда мы создаем экземпляр DefautHandler, методы внутри этого блока переопределяются? И в блоке конструктора, разрешено ли нам создавать переменные, как мы создали четыре логические переменные? Никогда не видел такого подхода в Java.

Может кто-нибудь помочь мне за то же ....?

Спасибо

1 Ответ

1 голос
/ 11 марта 2019

SAXParser - это интерфейс, и существует много синтаксических анализаторов XML, которые реализуют этот интерфейс. Если вы хотите узнать, как он работает, вам нужно выбрать один из этих XML-парсеров - наиболее доступным является парсер Apache Xerces. Вы можете начать здесь, но имейте в виду, что читать нелегко:

https://apache.googlesource.com/xerces2-j/+/f59f47412e404f4984480a45a99957ac07d287d4/src/org/apache/xerces/parsers/AbstractSAXParser.java

Проще говоря, парсер будет искать «<», а когда он его найдет, он вызывает вызываемый <code>ContentHandler startElement() метод с соответствующими параметрами.

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

Вы правы, что написание SAX ContentHandler (возможно, как расширение DefaultHandler) включает в себя довольно другой стиль программирования Java, чем вы могли бы привыкнуть. Поскольку ваш код обрабатывает события через обратные вызовы, вы не можете поддерживать текущее состояние в стеке так, как если бы у вас был основной цикл управления. Скорее вы должны подумать о том, как каждый вызов метода, такого как startElement () или characters (), влияет на текущее состояние, которое должно поддерживать ваше приложение, и решить, как изменить структуру данных, которая содержит это состояние. Это довольно другой способ программирования, и это одна из причин, по которой некоторые люди говорят, что интерфейсы синтаксического анализа "pull" проще в использовании, чем интерфейсы "push".

...