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