Используя Android SAXParser, один из моих XML-элементов таинственным образом ломается пополам

И это не '&'

Im, использующий объект SAXParser, анализирует фактический XML.

Обычно это делается путем передачи URL-адреса методу XMLReader.Parse. Поскольку мой XML поступает из запроса POST к веб-службе, я сохраняю этот результат как строку, а затем использую StringReader/InputSource для передачи этой строки обратно в метод XMLReader.Parse.

Однако что-то странное происходит с 2001-м символом XMLstring.
Метод 'characters' обработчика документа вызывается ДВАЖДЫ между методами startElement и endElement, фактически разрывая мою строку (в данном случае название проекта) на две части. Поскольку я создаю экземпляры объектов в методе символов, я получаю два объекта вместо одного.

Эта строка, около 2000 символов в строке, запускает «символы» два раза, разрываясь между «Нижний» и «Уровень».

<title>SUMC-BOOKSTORE, LOWER LEVEL RENOVATIONS</title>

Когда я обхожу обходной путь StringReader/InputSource и передаю простой файл XML в XMLReader.Parse, он работает абсолютно нормально.

Что-то в StringReader и/или InputSource как-то портит ситуацию.

Вот мой метод, который принимает и анализирует строку XML через SAXParser.

    public void parseXML(String XMLstring) {
    try {
        SAXParserFactory spf = SAXParserFactory.newInstance();
        SAXParser sp = spf.newSAXParser();
        XMLReader xr = sp.getXMLReader();
        xr.setContentHandler(this);

        // Something is happening in the StringReader or InputSource 
        // That cuts the XML element in half at the 2001 character mark.

        StringReader sr = new StringReader(XMLstring);
        InputSource is = new InputSource(sr);
        xr.parse(is);


    } catch (IOException e) {
        Log.e("CMS1", e.toString());
    } catch (SAXException e) {
        Log.e("CMS2", e.toString());
    } catch (ParserConfigurationException e) {
        Log.e("CMS3", e.toString());
    }
}

Я был бы очень признателен за любые идеи о том, как не запускать «символы» дважды, когда я доберусь до этой точки в строке XML.

Или покажите мне, как использовать запрос POST и при этом передавать URL-адрес функции Parse.

СПАСИБО.


person FauxReal    schedule 30.03.2010    source источник


Ответы (4)


Как сказал Донроби, синтаксический анализатор может вызывать метод символов более одного раза между startElement и endElement. Однако это вовсе не «плохое поведение», и вам не следует пытаться что-то придумать, чтобы этого не произошло. Похоже, ваш синтаксический анализатор использует буфер на 2000 символов, но есть и другие причины, по которым он может разбить текстовый узел на части.

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

person Paul Clapham    schedule 31.03.2010
comment
+1. Да, обычная обработка заключается в создании или подключении какого-либо аккумулятора в методе startElement, накоплении в нем в методе символов, а затем в использовании и удалении или отсоединении его в методе endElement. - person Don Roby; 31.03.2010

Метод символов может срабатывать несколько раз между startElement и endElement в SAXParser. Если ваша реализация не справляется с этим, скорее всего, используемый ContentHandler имеет метод неправильно закодированных символов.

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

См. Javadoc, отметив фразу

Синтаксические анализаторы SAX могут возвращать все непрерывные символьные данные в одном фрагменте или могут разбивать их на несколько фрагментов.

Этот Javadoc предназначен для ContentHandler. Похоже, вы используете DocumentHandler, который устарел в пользу ContentHandler. Но javadoc для DocumentHandler содержит идентичный язык.

person Don Roby    schedule 30.03.2010
comment
Спасибо, donroby Учитывая, что код дает плохие результаты только тогда, когда используются объекты StringReader и InputSource, мне кажется, что проблема кроется в этом. Когда я обхожу эту реализацию, она работает правильно, хотя и неудовлетворительно для производства. Учтите также, что независимо от порядка сортировки данных XML проблема возникает при вводе 2001 символа в XML. Спасибо! - person FauxReal; 31.03.2010
comment
Когда вы реализуете вещи неправильно, иногда они работают, несмотря на вашу ошибку. Проблема заключается в вашем коде, несмотря на то, что иногда кажется, что он работает. - person Don Roby; 31.03.2010

Большое спасибо вам обоим за ваши ответы. С вашей помощью мне удалось решить проблему.

Я выполнял фактическую обработку внутри метода «символов», чему я научился из онлайн-учебника.

Переместив обработку в метод endElement, я смог просто объединить символы в строку независимо от того, сколько раз срабатывали «символы».

Я добился этого довольно просто, настроив логическое значение betweenTags и установив его в true во время startElement и в false в конце endElement.

Внутренние символы, которые я добавил

if (betweenTags) accumulation += chars;

Строка накопления устанавливается в "" в конце startElement.

Сейчас работает отлично, сломанных элементов нет.

БЛАГОДАРНОСТЬ!

person FauxReal    schedule 31.03.2010
comment
Пожалуйста! Если вы сейчас примете ответ, это улучшит чью-то репутацию и ваш коэффициент принятия. - person Don Roby; 31.03.2010

Я была такая же проблема. Я изменил код синтаксического анализа на этот, и он сработал...!!!

@Override
    public void startElement(String arg0, String arg1, String arg2,
            Attributes arg3) throws SAXException {
        // TODO Auto-generated method stub
        currentstring = new String();
        if (arg1.equalsIgnoreCase("Order")) {
            currentItem = new HashMap<String, String>();
        }

    }


@Override
    public void characters(char[] arg0, int arg1, int arg2)
            throws SAXException {
        currentstring = currentstring + new String(arg0, arg1, arg2);
        Log.i("Current String", currentstring);
    }

@Override
    public void endElement(String arg0, String arg1, String arg2)
            throws SAXException {
        // TODO Auto-generated method stub
        if (currentItem != null) {
            currentItem.put(arg1, currentstring);
            currentstring = "";
        }

Идея состоит в том, чтобы инициализировать String в startElement(), добавить в character() и закончить в endElement().

person Rishabh Tayal    schedule 20.08.2013