Используя Android SAXParser, один мой my XML Elements таинственно разбивается пополам - PullRequest
2 голосов
/ 31 марта 2010

И это не '&'

Я использую объект SAXParser для синтаксического анализа фактического XML.

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

Однако, что-то странное происходит с 2001-м символом строки XML.
Метод «символов» обработчика документа вызывается TWICE между методами startElement и endElement, эффективно разбивая мою строку (в данном случае заголовок проекта) на две части. Поскольку я создаю объекты в методе символов, я получаю два объекта вместо одного.

Эта строка, около 2000 символов в строке, запускает «символы» два раза, пробивая между «Lower» и «Level»

<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.

СПАСИБО.

Ответы [ 4 ]

5 голосов
/ 31 марта 2010

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

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

2 голосов
/ 31 марта 2010

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

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

См. Javadoc , отмечая фразу

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

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

1 голос
/ 31 марта 2010

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

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

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

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

Внутри персонажей я добавил

if (betweenTags) accumulation += chars;

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

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

СПАСИБО!

0 голосов
/ 20 августа 2013

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

@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 = "";
        }

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

...