XmlRpcClientException: обнаружен недопустимый символ XML (Unicode: 0x8)

Я использую библиотеку Apache XML-RPC, чтобы получать сообщения об ошибках от Bugzilla. Вызывая службу, я получаю исключение: org.apache.xmlrpc.client.XmlRpcClientException: не удалось проанализировать ответ сервера: в содержимом элемента документа был обнаружен недопустимый символ XML (Unicode: 0x8).

Есть ли способ понять, где именно ошибка. Я обнаружил дату ошибок, что вызывает ошибку. Но их очень много. Могу ли я распечатать полученный xml или уточнить исключение?


person Konstantin Milyutin    schedule 31.05.2011    source источник
comment
Взгляните на это: stackoverflow.com/ questions / 2358522 /   -  person Karl-Bjørnar Øie    schedule 31.05.2011
comment
Привет, спасибо, я не знаю, что это backspace, но как получить ответ в виде строки или получить точное местоположение этого символа?   -  person Konstantin Milyutin    schedule 31.05.2011
comment
Об этой ошибке сообщается на bugzilla.mozilla.org, здесь.   -  person Ahmed Akhtar    schedule 23.05.2016


Ответы (1)


Уже поздно, но на случай, если кто-то наткнется на это.

Изменить:

Я занимаюсь этим уже два месяца и, наконец, нашел жизнеспособное решение вышеуказанной проблемы.

Эта проблема возникает из-за того, что иногда Bugzilla :: Webservice в ответ на удаленный вызов процедуры отправляет недопустимый символ в ответе XML.

Когда XML-RPC Apache пытается проанализировать этот ответ, он выдает следующую ошибку:

XmlRpcClientException: обнаружен недопустимый символ XML (Unicode: 0x8)

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

Найдите исходный код apache-xmlrpc как проект Eclipse здесь. (Импортируйте этот проект вместо файлов jar)

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

Итак, добавьте /apache-xmlrpc-3.1.3-src/client/src/main/java/org/apache/xmlrpc/client/util/XMLBufferredReader.java, например:

package org.apache.xmlrpc.client.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;

/**
 * @author Ahmed Akhtar
 *
 */
public class XMLBufferredReader extends BufferedReader
{
    /**
     * @param in
     */
    public XMLBufferredReader(Reader in)
    {
        super(in);
    }

    @Override
    public int read(char[] cbuf, int off, int len) throws IOException
    {
        int ret = super.read(cbuf, off, len);

        for(int i = 0; i < ret; i++)
        {
            char current = cbuf[i];

            if(!((current == 0x9) ||
                    (current == 0xA) ||
                    (current == 0xD) ||
                    ((current >= 0x20) && (current <= 0xD7FF)) ||
                    ((current >= 0xE000) && (current <= 0xFFFD)) ||
                    ((current >= 0x10000) && (current <= 0x10FFFF))))
            {
                cbuf[i] = 'r';
            }
        }

        return ret;
    }
}

Позже нам нужно отправить расширенный XMLBufferedReader в InputSource метода parse.

Функцию readResponse в файле /apache-xmlrpc-3.1.3-src/client/src/main/java/org/apache/xmlrpc/client/XmlRpcStreamTransport.java необходимо изменить на:

protected Object readResponse(XmlRpcStreamRequestConfig pConfig, InputStream pStream) throws XmlRpcException
{
        BufferedReader in = new XMLBufferredReader(new BufferedReader(new InputStreamReader(pStream, StandardCharsets.UTF_8)));

        InputSource isource = new InputSource(in);
        XMLReader xr = newXMLReader();
        XmlRpcResponseParser xp;
        try {
            xp = new XmlRpcResponseParser(pConfig, getClient().getTypeFactory());
            xr.setContentHandler(xp);
            xr.parse(isource);
        } catch (SAXException e) {
            throw new XmlRpcClientException("Failed to parse server's response: " + e.getMessage(), e);
        } catch (IOException e) {
            throw new XmlRpcClientException("Failed to read server's response: " + e.getMessage(), e);
        }
        if (xp.isSuccess()) {
            return xp.getResult();
        }
        Throwable t = xp.getErrorCause();
        if (t == null) {
            throw new XmlRpcException(xp.getErrorCode(), xp.getErrorMessage());
        }
        if (t instanceof XmlRpcException) {
            throw (XmlRpcException) t;
        }
        if (t instanceof RuntimeException) {
            throw (RuntimeException) t;
        }
        throw new XmlRpcException(xp.getErrorCode(), xp.getErrorMessage(), t);
}

После этого расширения для клиента Apache XML-RPC все должно работать нормально.

Примечание. Остальная часть этого сообщения - это исходное решение, которое я опубликовал, и это обходной путь в случае, если кто-то не хочет расширять клиент Apache XML-RPC.

Старое сообщение:

Если вы используете Bugzilla :: Служебная функция Webservice :: Bug :: search с некоторыми параметрами offset и limit вместе с критериями поиска.

Вы получите это исключение для некоторых конкретных значений, скажем, x из offset и y из limit, которые вы можете узнать, запустив в режиме отладки.

Теперь вызовите функцию search, сохранив x как смещение, а 1 как limit, а затем выполните цикл и увеличивайте x, пока не достигнет значения x + y как смещения, сохраняя limit как 1.

Таким образом, вы будете извлекать ошибки по очереди и, работая в режиме отладки, вы можете определить точную ошибку, которая вызывает исключение.

Для x = 21900 и y = 100 сделайте что-нибудь вроде:

for(int i = 21900; i <= 22000; i++)
{
 result = ws.search(searchCriteria, i, 1);
}

Запустив это в режиме отладки, я обнаружил, что фактическая offset, вызывающая ошибку, была 21963, поэтому я написал код, чтобы избежать этой конкретной ошибки:

if(offset != 21900)
{
 result = obj.search(productNames, offset, limit);
 bugsObj = (Object[])result.get("bugs");
}
else
{
 result = obj.search(productNames, 21900, 63);
 Object[] bugsObj1 = (Object[])result.get("bugs");
 result = obj.search(productNames, 21964, 36);
 Object[] bugsObj2 = (Object[])result.get("bugs");
 bugsObj = new Object[bugsObj1.length+bugsObj2.length];

 for(int i = 0; i < bugsObj1.length + bugsObj2.length; i++)
 {
  bugsObj[i] = i < bugsObj1.length ? bugsObj1[i] : bugsObj2[i - bugsObj1.length];
 }
}
person Ahmed Akhtar    schedule 29.04.2016