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

发布于 2024-11-11 18:22:02 字数 221 浏览 1 评论 0原文

我正在使用 Apache XML-RPC 库从 Bugzilla 获取错误。调用该服务,我收到异常: org.apache.xmlrpc.client.XmlRpcClientException:无法解析服务器的响应:在文档的元素内容中发现无效的 XML 字符(Unicode:0x8)。

有没有办法了解错误到底在哪里。我找到了错误的日期,这导致了错误。但它们有很多。我可以打印收到的 xml 或使异常更精确吗?

I'm using Apache XML-RPC library to get bugs from Bugzilla. Calling the service, I receive exception:
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.

Is there a way to understand where exactly mistake is. I located a date of bugs, which causes mistake. But there are a lot of them. Can I print the received xml or make exception more precise?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

娇俏 2024-11-18 18:22:02

已经晚了,但以防万一有人偶然发现这一点。

编辑:

我已经研究了两个月了,终于找到了解决上述问题的可行方法。

出现此问题的原因是 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

文件 /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 参数以及搜索条件。

您会在某些特定值上遇到此异常,例如 offsetxlimity,您可以通过在调试模式下运行来找出答案。

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

这样,您将一次提取一个错误并在调试模式下运行,您可以确定导致异常的确切错误。

对于 x = 21900y = 100 执行以下操作:

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

在调试模式下运行此命令,我发现导致错误的实际 offset 为 < code>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];
 }
}

Its late but in case someone stumbles upon this.

Edit:

I have been on this for two months now and finally I have found a viable solution to the above problem.

This issue occurs because Bugzilla::Webservice sometimes, in response to a, remote procedure call, sends an invalid character in the XML response.

When Apache's XML-RPC tries to parse that response, it gives the following error:

XmlRpcClientException: An invalid XML character (Unicode: 0x8) was found

To solve this issue, Apache's XML-RPC Client needs to be extended to clean the response off invalid XML characters before trying to parse it.

Find the source code of apache-xmlrpc as an Eclipse project here. (Import this project instead of the jar files)

To do this, we first need to extend the BufferedReader class to replace any invalid XML character before it returns.

So, add /apache-xmlrpc-3.1.3-src/client/src/main/java/org/apache/xmlrpc/client/util/XMLBufferredReader.java, like this:

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;
    }
}

Later, we need to send in the extended XMLBufferedReader to the InputSource of the parse method.

The function readResponse in the file /apache-xmlrpc-3.1.3-src/client/src/main/java/org/apache/xmlrpc/client/XmlRpcStreamTransport.java needs to be changed to:

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);
}

After this extension to the Apache's XML-RPC Client, everything should work fine.

Note: The rest of this post, is the initial solution that I posted, which is a workaround in case someone does not want to extend Apache's XML-RPC client.

Old Post:

In case you are using the Bugzilla::Webservice::Bug::search utility function with some offset and limit parameters along with the search criteria.

You would be getting this exception on some specific values lets say x of offset and y of limit which you can find out by running in debug mode.

Now call the search function by keeping x as offset and 1 as limit and then loop and increment x until it reaches a value of x + y as offset while still keeping limit as 1.

This way you will be extracting bugs one at a time and running in debug mode you can determine the exact bug which is causing the exception.

For x = 21900 and y = 100 do something like:

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

Running this in debug mode I found out that the actual offset causing the bug was 21963 so then I wrote code to avoid that specific bug:

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];
 }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文