Парсер JAVA SAX разделяет вызовы символов () - PullRequest
21 голосов
/ 31 декабря 2010

Я делаю проект для анализа некоторых данных из 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 << ============ разделить сообщение </p>

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

Имеет ли XML какой-то "\ n" или "\ r" ???

Ответы [ 4 ]

35 голосов
/ 31 декабря 2010

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

8 голосов
/ 31 декабря 2010

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

См. Ниже из JavaDoc ContentHandler.characters (...)

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

5 голосов
/ 02 сентября 2013

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

  • добавить «глобальную» переменную содержимого
  • , а затем обнулить ее в методе запуска (content == null)
  • в методе end вы можете распечатать или добавить эту строку содержимого к какому-либо объекту
  • в символьном методе u можете сделать если / else:

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

    Brutal way (лучшесделать это с помощью stringbuilder), но работает, и «строка» больше не разделяется.

3 голосов
/ 31 декабря 2010

Это особенность SAX.Синтаксический анализатор может разбивать сегменты Text и вызывать ваш метод characters столько раз, сколько ему захочется.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...