1

我在一个 Android 应用程序中有一些 XML,其中 XmlPullParser 是将 XML 绑定到数据模型类的推荐解决方案。XmlPullParser 的 Android 文档相当不错,除了如何处理元素间空白。推荐的方法是检测低级 IGNORABLE_WHITESPACE 解析事件并跳过这些事件。但是对于我试图接受的 XML,这种方法对我不起作用。我从来没有看到发生过低级别的 IGNORABLE_WHITESPACE 事件。这让我相信我没有正确理解我的特定用例的某些方面,无论是 XmlPullParser 行为、可接受的 XML,还是可能的配置问题。

我试图接受的 XML 片段的简化测试用例是:

<a>  <b></b>  </a>

我使用推荐的 getNextToken() 方法来接受这个元素的代码破解是:

            boolean hasEvent = false;
            String desc = null;
            while (!hasEvent) {
                result = xpp.nextToken();
                desc = xpp.getPositionDescription();
                Log.i(TAG, String.format("Processing: %s", desc));
                switch (result) {
                case START_TAG:
                case END_TAG:
                case END_DOCUMENT:
                    hasEvent = true;
                    break;

                case TEXT:
                    // Use a real hack to detect whitespace.
                    if (desc.contains("TEXT (whitespace)@")) {
                        hasEvent = false;
                    } else {
                        hasEvent = true;
                    }
                    break;

                default:
                    break;
                }
            }

我看到的结果基本上是:得到 START_TAG(a),得到 TEXT(空白),得到 START_TAG(b),得到 END_TAG(b),得到 TEXT(空白),得到 END_TAG(a)。

所以问题是:我没有正确理解什么?我如何接受这个序列而不诉诸丑陋的黑客,这更符合推荐使用 XmlPullParser。

我有一种预感,这是有问题的 XML,但它代表了我将要呈现的内容,即我无法控制输入流中的元素间空白。

fwiw,XML 的简单框架可以毫无问题地处理这个输入流,这是我的首选方法,但是由于与底层 stax 和 epp 库的依赖冲突,该包与 Gradle 和 Android Studio 一起使用非常非常混乱,但那是完全是另一个问题。

4

1 回答 1

0

为了在某​​种程度上回答我自己的问题,我为在某些时候发现自己处于我境地的开发人员提供以下内容。但我非常期待很快会有更好的答案。

至于缺乏理解,第一点是现在我明白我正在使用非验证解析器。此声明是在 Android XmlPullParser 源代码/Javadoc for isWhitespace() 中提出的:

请注意:非验证解析器无法区分空格和可忽略的空格,除了根元素之外的空格。可忽略的空白被报告为单独的事件,仅通过 nextToken 公开。

这使我相信 JAXB 和 Simple 正在验证解析器并且可以大步处理这个元素间空白,而我现在必须明确地处理它,这让我很懊恼。

缺乏理解的第二点是,Android 的 XmlPullParser 只能通过提供“模式”来支持验证来创建验证解析器,这对于这个实例来说几乎是我无法控制的。

至于处理元素间空格的更优雅的方法,我的答案是有两种方法: getNextElement() 它将返回下一个 START_TAG 或 END_TAG 事件,但丢弃文本为空格的所有 TEXT 事件,其他的都是视为解析错误;另一种方法是 getNextText(),它将从 TEXT 或 CDSECT 解析事件中返回文本,并将任何其他事件报告为错误。

正如我所说,我期待着更好的答案。

于 2014-03-02T06:46:51.167 回答