2

它不是'&'

我使用 SAXParser 对象来解析实际的 XML。

这通常通过将 URL 传递给 XMLReader.Parse 方法来完成。因为我的 XML 来自对 Web 服务的 POST 请求,所以我将该结果保存为字符串,然后使用 StringReader / InputSource 将此字符串反馈给 XMLReader.Parse 方法。

但是,在 XMLstring 的第 2001 个字符处发生了一些奇怪的事情。
文档处理程序的“字符”方法在 startElement 和 endElement 方法之间被调用两次,有效地将我的字符串(在本例中为项目标题)分成两部分。因为我在我的角色方法中实例化对象,所以我得到了两个对象而不是一个。

这条线,大约 2000 个字符到字符串中会触发“字符”两次,在“Lower”和“Level”之间中断

<title>SUMC-BOOKSTORE, LOWER LEVEL RENOVATIONS</title>

当我绕过 StringReader / InputSource 解决方法并将平面 XML 文件提供给 XMLReader.Parse 时,它​​工作得非常好。

关于 StringReader 和/或 InputSource 的某些东西以某种方式搞砸了。

这是我通过 SAXParser 获取和解析 XML 字符串的方法。

    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

4 回答 4

5

正如 donroby 所说,解析器在 startElement 和 endElement 之间多次调用 characters 方法是完全合法的。然而,这根本不是“行为不端”,你不应该试图搞砸事情,以免它发生。您的解析器似乎正在使用 2000 个字符的缓冲区,但还有其他原因可能会将文本节点分成几部分。

您应该做的是在 characters 方法中累积数据并稍后在 endElement 方法中处理它,当您确定您已经为节点累积了所有字符数据时。

于 2010-03-31T04:12:11.510 回答
2

在 SAXParser 中的 startElement 和 endElement 之间多次触发 characters 方法是合法的。如果您的实现没有处理它,很可能正在使用的 ContentHandler 具有错误编码的字符方法。

从代码片段中,我认为行为不端的字符方法在您的代码中的其他地方,因为您将“this”作为 ContentHandler 传递。发布该代码,也许我们可以帮助修复它。

请参阅Javadoc,注意该短语

SAX 解析器可以在单个块中返回所有连续的字符数据,也可以将其拆分为多个块

此 Javadoc 用于 ContentHandler。看来您正在使用 DocumentHandler,它已被弃用,取而代之的是 ContentHandler。但是 DocumentHandler 的 javadoc 包含相同的语言。

于 2010-03-30T23:39:18.727 回答
1

非常感谢你们的回复。在您的帮助下,我能够解决问题。

我在“字符”方法中进行实际处理,这是我从在线教程中学到的。

通过将处理移至 endElement 方法,我能够简单地将字符连接成一个字符串,而不管“字符”触发了多少次。

我通过在标签之间设置一个布尔值并在 startElement 期间将其设置为 true 并在 endElement 结束时设置为 false 来完成此操作。

内部字符,我已添加

if (betweenTags) accumulation += chars;

累积字符串在 startElement 的末尾设置为“”。

现在效果很好,没有损坏的元素。

谢谢!

于 2010-03-31T16:12:07.487 回答
0

我遇到过同样的问题。我将解析代码更改为此,它工作......!!!

@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() 中初始化字符串,在 character() 中追加并在 endElement() 中完成。

于 2013-08-20T17:45:24.880 回答