Подтвердить что ты не робот

Парсер JAVA SAX разделяет вызовы на символы()

Я делаю проект для анализа некоторых данных из XML.

Например, XML

<abc>abcdefghijklmno</abc>

Мне нужно разобрать "abcdefghijkmnlp".

Но пока я проверяю свой синтаксический анализ, я обнаруживаю большую проблему:

public class parser{
    private boolean hasABC = false;


        //Constructor HERE
        ......................
        ......................

     @Override
     public void startDocument () throws SAXException{  
     }

     @Override
     public void endDocument () throws SAXException{  
     }

     @Override
     public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException{  
          if ("abc".equalsIgnoreCase(localName)) {
              this.hasABC = true;
          }
      }
      @Override
      public void endElement(String namespaceURI, String localName, String qName) throws SAXException{
            if ("abc".equalsIgnoreCase(localName)) {
                 this.hasABC = false;
            }
       }
       @Override
       public void characters(char ch[], int start, int length){
            String content = new String(ch, start, length).trim(); 
            if(this.hasABC){
                 System.out.println("ABC = " + content);
            }
        }
    }

Я обнаружил, что парсер проанализировал тег два раза Распечатка системы,

ABC = abcdefghi

ABC = jklmno < ============= разделите сообщение

Почему парсер автоматически вызывает символы() два раза????

Является ли XML имеющим некоторые "\n" или "\ r"???

4b9b3361

Ответ 1

Parser вызывает метод characters более одного раза, поскольку он может и разрешен для каждой спецификации. Это помогает быстрому парсеру и снижать уровень памяти. Если вы хотите, чтобы одна строка создавала новый объект StringBuilder в startElement и обрабатывали его по методу endElement.

Ответ 2

Вы будете удивлены, но это документированное поведение, то есть вы не можете предположить, что синтаксический анализатор будет читать и возвращать все текстовые данные элемента в одном обратном вызове. Раньше у меня был такой же опыт. Вам необходимо закодировать эту ситуацию, или вы можете переключиться на парсер Stax. Вы можете использовать CharArrayWriter для накопления данных по нескольким обратным вызовам.

См. ниже JavaDoc of ContentHandler.characters(...)

Парсер вызовет этот метод для сообщает каждый фрагмент символьных данных. Анализаторы SAX могут возвращать все смежные символьные данные в одном фрагменте или они могут разделить на несколько кусков; однако все символы в любом одно событие должно происходить из одного и того же внешний объект, чтобы локатор предоставляет полезную информацию.

Ответ 3

Вы можете изменить метод начала, конца и символа, например:

  • добавить "глобальную" переменную содержимого
  • затем null в методе start (content == null)
  • в конце метода u может println или добавить эту строку содержимого к некоторому объекту
  • в методе символов u может сделать if/else:

    if (content == null)
    {
        content = new String(ch, start, length);
    } else {
        content += new String(ch, start, length);
    }
    

    Брутальный путь (лучше сделать это с помощью stringbuilder), но работает, а "строка" больше не разделяется.

Ответ 4

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

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