XmlRpcClientException:发现一个无效的XML字符Unicode:0x8

问题描述

|| 我正在使用Apache XML-RPC库从Bugzilla中获取错误调用该服务,我收到异常: org.apache.xmlrpc.client.XmlRpcclientException:无法解析服务器的响应:在文档的元素内容中发现了无效的XML字符(Unicode:0x8)。 有没有办法了解错误在哪里。我找到了一个错误的日期,这会导致错误。但是有很多。我可以打印收到的xml或使异常更精确吗?     

解决方法

        为时已晚,但万一有人偶然发现。 编辑: 我已经研究了两个月,终于找到了解决上述问题的可行方法。 发生此问题的原因是,有时Bugzilla :: Webservice在响应远程过程调用时会在XML响应中发送无效字符。 当Apache \的XML-RPC尝试解析该响应时,会出现以下错误:   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
发送到
parse
方法的
InputSource
。 文件“ 7”中的功能“ 6”需要更改为:
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);
}
在对Apa​​che \的XML-RPC客户端进行此扩展之后,一切都应该正常工作。 注意:本文的其余部分是我发布的初始解决方案,如果有人不想扩展Apache的XML-RPC客户端,这是一种解决方法。 旧帖子: 如果您使用的是Bugzilla :: Webservice :: Bug :: search实用程序函数,带有一些
offset
limit
参数以及搜索条件。 您可能会在某些特定值上遇到此异常,比如说ѭ9的
x
和ѭ10的ѭ13by,您可以通过在调试模式下运行找到它们。 现在调用
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);
}
在调试模式下运行此命令,我发现导致该错误的实际“ 9”是“ 27”,因此我编写了代码以避免该特定的错误:
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];
 }
}