Android 1.5 和 dom4j - 属性名称解析不正确

发布于 2024-10-16 08:38:19 字数 1797 浏览 1 评论 0原文

我正在开发 Android 1.5 的应用程序。目前,我需要解析 XML 文件。由于 Android 在 API Level 3 中不原生支持 XPath,因此我决定使用 dom4j 和 jaxen 库来读取文件。

我有简单的 XML 文件 (test1.xml):

<?xml version="1.0" encoding="utf-8" ?>
<tests>
    <resources base_lang="en">
            <string base="example">
                    <localization lang="pl">Przykład</localization>
            </string>
    </resources>
    <test name="main name">
            <title>Main Title</title>
            <description>Long description</description>
    </test>
</tests>

和简单的代码:

SAXReader reader = new SAXReader();
Document doc = reader.read("file:///sdcard/tests/test1.xml");
Node node = doc.selectSingleNode("/tests/test");
Element elem = (Element)node;
for(int j=0;j<elem.attributeCount();++j) {
    Attribute attr = elem.attribute(j);
    Logger.getLogger(AutoTesterMain.class.getName()).log(Level.SEVERE, "ATTR: "+attr.getName()+"="+attr.getValue());
}

它读取 test1.xml 文件,找到“/tests/test”节点并枚举它的属性。当我将这段代码作为“桌面”java应用程序的一部分运行时(我对java术语并不深入),它显示了我所期望的内容(Fedora Linux下的OpenJDK 1.8.3):

SEVERE: ATTR: name=main name

不幸的是,在Android 1.5(模拟器ofc)中,完全相同的代码显示:

E/AutoTesterMain(  823): ATTR: base_lang=main name

如您所见,属性的值正常,但名称有问题。我完全不知道为什么在这个地方会出现来自完全其他 DOM 元素(“/tests/resources”)的属性名称。它似乎错误地解析了我的文件,所以我可能设置了错误......

当然,两个版本都使用完全相同的 .jar 和 dom4j 和 jaxen 库,所以这可能没问题。

这个问题比仅仅列出不正确的属性产生的影响更大。它还不允许我使用 XPath 正确读取属性 - 选择“/tests/test/@name”没有给出任何内容,而“/tests/test/@base_lang”给出了“main name”字符串。这显然是由与上面列出属性相同的错误引起的。

有人遇到过这个吗?我该如何解决它?

不幸的是,迁移到具有原生 XPath 支持的较新 Android 对我来说不是一个选择。

我试图在网上和这里找到任何东西,但没有运气。

I am working on application for Android 1.5 . Currently, I need to parse XML file. As Android does not support XPath natively in API Level 3, I decided to use dom4j and jaxen libraries to read a file.

I have simple XML file (test1.xml):

<?xml version="1.0" encoding="utf-8" ?>
<tests>
    <resources base_lang="en">
            <string base="example">
                    <localization lang="pl">Przykład</localization>
            </string>
    </resources>
    <test name="main name">
            <title>Main Title</title>
            <description>Long description</description>
    </test>
</tests>

And simple code:

SAXReader reader = new SAXReader();
Document doc = reader.read("file:///sdcard/tests/test1.xml");
Node node = doc.selectSingleNode("/tests/test");
Element elem = (Element)node;
for(int j=0;j<elem.attributeCount();++j) {
    Attribute attr = elem.attribute(j);
    Logger.getLogger(AutoTesterMain.class.getName()).log(Level.SEVERE, "ATTR: "+attr.getName()+"="+attr.getValue());
}

It reads test1.xml file, finds "/tests/test" node and enumerates it's attributes. When I run this code as part of "desktop" java application (I'm not deep in the java terminology), it displays what I expect (OpenJDK 1.8.3 under Fedora Linux):

SEVERE: ATTR: name=main name

Unfortunately, in Android 1.5 (emulator ofc), the exact same code shows:

E/AutoTesterMain(  823): ATTR: base_lang=main name

As you can see, attribute's value is OK, but there's problem with name. I have completely no idea, why in this place appears name of attribute from completely other DOM element ("/tests/resources"). It seems to parse my file incorrectly, so I probably set something wrong ...

Of course both versions uses the exact same .jars with dom4j and jaxen libraries, so this is probably ok.

This problem has more effects than only incorrect attributes listing. It also disallows me to read attributes properly using XPath - selection "/tests/test/@name" gives nothing, while "/tests/test/@base_lang" gives me "main name" string. This is obviously caused by the same error as in listing attributes above.

Does anyone encountered this? How could I fix it?

Moving to newer Android with native XPath support is unfortunately not an option for me.

I was trying to find anything on web and here, but had no luck.

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

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

发布评论

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

评论(1

晌融 2024-10-23 08:38:19

在模拟器 Android 2.1 上运行我的应用程序时,我遇到了同样的问题。虽然对于 2.2 来说它工作得很好。我使用的dom4j lib版本是v1.6。

正如您从下面的摘录中看到的,所有属性名称都替换为我的 xml 文件中第一个属性的名称:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ncx PUBLIC "-//NISO//DTD ncx 2005-1//EN" "http://www.daisy.org/z3986/2005/ncx-2005-1.dtd"><ncx xmlns="http://www.daisy.org/z3986/2005/ncx/" version="2005-1">
    <head>
        <meta version="dtb:uid" version="6efac3c8-0d51-46bd-b125-58dae01bf92e"/>
        <meta version="dtb:depth" version="4"/>
        <meta version="dtb:totalPageCount" version="0"/>
        <meta version="dtb:maxPageNumber" version="0"/>
    </head>
    <docTitle>
        <text>Book</text>
    </docTitle>
    <navMap>
        <navPoint version="navPoint-1" version="1">
            <navLabel>
                <text>Header1</text>
            </navLabel>
            <content version="Text/Section0001.xhtml"/>
            <navPoint version="navPoint-2" version="2">

当实际的 xml 为:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ncx PUBLIC "-//NISO//DTD ncx 2005-1//EN"
   "http://www.daisy.org/z3986/2005/ncx-2005-1.dtd">

<ncx xmlns="http://www.daisy.org/z3986/2005/ncx/" version="2005-1">
    <head>
        <meta name="dtb:uid" content="6efac3c8-0d51-46bd-b125-58dae01bf92e"/>
        <meta name="dtb:depth" content="4"/>
        <meta name="dtb:totalPageCount" content="0"/>
        <meta name="dtb:maxPageNumber" content="0"/>
    </head>
    <docTitle>
        <text>Book</text>
    </docTitle>
    <navMap>
        <navPoint id="navPoint-1" playOrder="1">
            <navLabel>
                <text>Header1</text>
            </navLabel>
            <content src="Text/Section0001.xhtml"/>
            <navPoint id="navPoint-2" playOrder="2">

似乎 xml 文档解析不正确。这是我的源代码:

inputStream = new FileInputStream(ncfPath);
SAXReader reader = new SAXReader(); // dom4j SAXReader
Document document = reader.read(inputStream);
String xml = document.asXML();

如果您找到了此问题的解决方案,请告诉我。

编辑: dom4j 2.0 alpha 2 存在同样的问题
EDIT2:终于我找到了解决方案。问题确实出在dom4j源代码中。这是链接大约两年前(!)记录的问题。
要修复它,您需要在 \dom4j-1.6.1\src\java\org\dom4j\tree\NamespaceStack.java 中使用正确的以下方法:

public QName getAttributeQName(String namespaceURI, String localName, String qualifiedName) {
    // Fix: qualifiedName is empty on Android 2.1
    // refer to https://sourceforge.net/tracker/index.php?func=detail&aid=2789052&group_id=16035&atid=116035#
        if (qualifiedName == null || qualifiedName.length() == 0) {
            qualifiedName = localName;
        }

I have same issue when running my app on emulator Android 2.1. Although for 2.2 it works perfectly. The version of the dom4j lib I am using is v1.6.

As you can see from the following extract all attribute names are replaced with the name of the first attribute in my xml file:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ncx PUBLIC "-//NISO//DTD ncx 2005-1//EN" "http://www.daisy.org/z3986/2005/ncx-2005-1.dtd"><ncx xmlns="http://www.daisy.org/z3986/2005/ncx/" version="2005-1">
    <head>
        <meta version="dtb:uid" version="6efac3c8-0d51-46bd-b125-58dae01bf92e"/>
        <meta version="dtb:depth" version="4"/>
        <meta version="dtb:totalPageCount" version="0"/>
        <meta version="dtb:maxPageNumber" version="0"/>
    </head>
    <docTitle>
        <text>Book</text>
    </docTitle>
    <navMap>
        <navPoint version="navPoint-1" version="1">
            <navLabel>
                <text>Header1</text>
            </navLabel>
            <content version="Text/Section0001.xhtml"/>
            <navPoint version="navPoint-2" version="2">

When the actual xml is :

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ncx PUBLIC "-//NISO//DTD ncx 2005-1//EN"
   "http://www.daisy.org/z3986/2005/ncx-2005-1.dtd">

<ncx xmlns="http://www.daisy.org/z3986/2005/ncx/" version="2005-1">
    <head>
        <meta name="dtb:uid" content="6efac3c8-0d51-46bd-b125-58dae01bf92e"/>
        <meta name="dtb:depth" content="4"/>
        <meta name="dtb:totalPageCount" content="0"/>
        <meta name="dtb:maxPageNumber" content="0"/>
    </head>
    <docTitle>
        <text>Book</text>
    </docTitle>
    <navMap>
        <navPoint id="navPoint-1" playOrder="1">
            <navLabel>
                <text>Header1</text>
            </navLabel>
            <content src="Text/Section0001.xhtml"/>
            <navPoint id="navPoint-2" playOrder="2">

It seems that xml document is parsed incorrectly. Here is my source code:

inputStream = new FileInputStream(ncfPath);
SAXReader reader = new SAXReader(); // dom4j SAXReader
Document document = reader.read(inputStream);
String xml = document.asXML();

Let me know if you have found solution for this issue.

EDIT: same issue for the dom4j 2.0 alpha 2
EDIT2: finally I've found a solution. The problem indeed in dom4j source code. Here is the link to the issue recorded almost two years(!) ago.
To fix it you need correct following method in \dom4j-1.6.1\src\java\org\dom4j\tree\NamespaceStack.java:

public QName getAttributeQName(String namespaceURI, String localName, String qualifiedName) {
    // Fix: qualifiedName is empty on Android 2.1
    // refer to https://sourceforge.net/tracker/index.php?func=detail&aid=2789052&group_id=16035&atid=116035#
        if (qualifiedName == null || qualifiedName.length() == 0) {
            qualifiedName = localName;
        }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文