XmlRpcClientException:发现无效的XML字符(Unicode:0x8)

4

我正在使用Apache XML-RPC库从Bugzilla获取缺陷信息。调用服务时,我收到异常信息:org.apache.xmlrpc.client.XmlRpcClientException: Failed to parse server's response: An invalid XML character (Unicode: 0x8) was found in the element content of the document.

是否有办法找出具体错误位置?我已经定位到了导致错误的缺陷日期,但是缺陷很多。我能打印接收到的XML或使异常更加精确吗?


1
看一下这个:https://dev59.com/nUzSa4cB1Zd3GeqPlUkG - Karl-Bjørnar Øie
嗨,谢谢。我知道它是退格键,但如何将回复作为字符串获取或获取该字符的确切位置? - Konstantin Milyutin
这是一个在 bugzilla.mozilla.org 上报告的错误 here - Ahmed Akhtar
1个回答

1

如果有人偶然发现这篇文章,我很晚才回复。

编辑:

我已经在这个问题上花了两个月的时间,终于找到了一个可行的解决方案。

这个问题是由于Bugzilla::Webservice有时会在远程过程调用的响应中发送无效的字符造成的。

当Apache的XML-RPC尝试解析该响应时,将出现以下错误:

XmlRpcClientException:发现无效的XML字符(Unicode:0x8)

为了解决这个问题,需要扩展Apache的XML-RPC客户端以在尝试解析之前清除无效的XML字符。

在此处找到apache-xmlrpc的源代码作为Eclipse项目here。(导入此项目而不是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发送到parse方法的InputSource中。
文件/apache-xmlrpc-3.1.3-src/client/src/main/java/org/apache/xmlrpc/client/XmlRpcStreamTransport.java中的函数readResponse需要更改为:
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实用程序函数与一些offsetlimit参数以及搜索条件。

您将在某些特定值上得到这个异常,比如说xoffsetylimit,您可以通过在调试模式下运行来找到它们。

现在调用search函数,保持x为偏移量,1limit,然后循环并递增x,直到它达到x + y作为偏移量的值,同时仍然保持limit1

这样做,您将一次提取一个错误,并在调试模式下运行,您可以确定导致异常的确切错误。对于 x = 21900 和 y = 100,可以执行以下操作:
for(int i = 21900; i <= 22000; i++)
{
 result = ws.search(searchCriteria, i, 1);
}

在调试模式下,我发现导致错误的实际偏移量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];
 }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接