3

Im having troubles inserting a java classes I wrote into my android application. As a standalone java application, it works fine. once I take the classes and put them inside my android app, I have an exception when trying to manipulate xml object. I use the following:

import org.w3c.dom.Element;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSSerializer;

What I do is basically this:

Document doc;
Element root = GetRootElement("root");
Element nameElement;
nameElement = doc.createElement("x");
nameElement.setTextContent("y");
root.appendChild(nameElement);

DOMImplementationLS domImplementation = (DOMImplementationLS) doc.getImplementation();
LSSerializer lsSerializer = domImplementation.createLSSerializer();
return lsSerializer.writeToString(doc); //sends the xml's string somewhere else in the code

Now, running this code as a regular java application works, but in an android app, it will fail in the doc.getImplementation() line, with the following error:

Caused by: java.lang.ClassCastException: org.apache.harmony.xml.dom.DOMImplementationImpl cannot be cast to org.w3c.dom.ls.DOMImplementationLS

I tried to give as much as info as possible, I hope it helps.

buddy123
  • 5,679
  • 10
  • 47
  • 73
  • Evidently Android is using [Xerces](http://xerces.apache.org/xerces-j/apiDocs/index.html) rather than org.w3c.dom. You should be able to accomplish the same thing with Xerces' XMLSerializer – Ray Stojonic Oct 11 '13 at 11:59

3 Answers3

2

DOMImplementationLS doesn't seem to be available on Android 4.1 at least (my device is running that version, so I can't confirm about newer ones). The interface exists, but isn't implemented by the object you get from getImplementation(), as you mention.

Apart from the cast, another official way to get this object is like this:

(DOMImplementationLS)doc.getImplementation().getFeature("LS", "3.0");

However, this returns null on Android 4.1.

I did some looking around but unfortunately, the only way I found to solve this problem is to serialize XML the 'old' way using a Transformer. This does work on my device, and the interface is present since API level 8 (Android 2.2).

Transformer transformer = TransformerFactory.newInstance().newTransformer();
StringWriter stringWriter = new StringWriter();
transformer.transform(new DOMSource(doc), new StreamResult(stringWriter));
String xml = stringWriter.toString();

This is an older method, and you can also rely on it for desktop Java. However, it might behave differently from the LSSerializer, and normally runs slower.

(Note: My code example above shows how to serialize the entire document, because that's all I needed. It might work to serialize a single element if you put that in the DOMSource constructor, otherwise you might have to create a new document, insert the element in it, and serialize that...)

sam
  • 2,105
  • 2
  • 15
  • 18
0

In the code you've listed:

Document doc;
Element root = GetRootElement("root");
Element nameElement;
nameElement = doc.createElement("x");

doc.createElement("x"); would give a NullPointerException.

You created a Document somehow but don't show it, and it is that bit of code that ends up being most important to solving your problem.

Here's what I think is going on: on your desktop, you've written code that uses the w3c xml classes, however, when you deploy it to Android, Android is using Xerces.

As Document is an interface, you'll get an implementation Object of whatever type the underlying system provides, which, in this case, is a CoreDocumentImpl from Xerces rather than the w3c class your code expects.

Ray Stojonic
  • 1,260
  • 1
  • 7
  • 11
-1

from the error produced, one can assume that the doc.getImplementation method returns an object of class DOMImplementationImpl from the package org.apache.harmony.xml.dom but you are casting it into a class named DOMImplementationImpl that is in a package org.w3c.dom.ls

its like this,

package sample1;
public class SampleClass {
}

package sample2;
public class SampleClass{
}

package sample3;
import sample2.SampleClass
public class ReturningClass{
  public Object returnSampleClass() {
    return new SampleClass(); // returns the object from package sample2
  }
}

package test;

import sample1.SampleClass; //importing class from sample1
import sample3.ReturningClass;

public class Test {

public static void main(String[] args) {
  ReturningClass returner = new ReturningClass();
  SampleClass s =  (SampleClass)returner.returnSampleClass(); 
  //conflict arises as incompatible class types
}

}
Thirumalai Parthasarathi
  • 4,541
  • 1
  • 25
  • 43
  • Yes, I know what it seems like. But I dont know other way to convert my xml document to a string. also, a regular java app is not raising any errors about it. only in android. so that makes me even more curious about it. – buddy123 Oct 11 '13 at 12:14
  • are you saying that `DOMImplementationLS domImplementation = (DOMImplementationLS) doc.getImplementation();` gets compiled in a desktop? i dont think so... unless both are the same class type – Thirumalai Parthasarathi Oct 11 '13 at 12:19
  • Yes, That is exactly what I say. I wrote this external classes at first as a library, but couldnt understand why its not working. then, when I added the source code itself, I noticed this error is because of that line. What alternative do I have to convert the document to a string? Anyway, the getImplementation does return a DOMImplementationLS, thats the API – buddy123 Oct 11 '13 at 12:23
  • @Bonjo : im not sure you quite understand the scenario here. `getImplementation` does return a DOMImplemenationLS for sure. i know that, but when it returns that object, you are trying to refer it with a class from another package. its like trying to refer a String object with an Integer reference. – Thirumalai Parthasarathi Oct 11 '13 at 12:32