SchemaFactory no es compatible con W3C XML Schema en plataforma nivel 8?

Con el SDK de Android, falla el siguiente código en una actividad simple vacía:

@Override protected void onStart() { super.onStart(); SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); } 

El logcat de emulador 2.2 muestra esta excepción:

 06-28 05:38:06.107: WARN/dalvikvm(495): threadid=1: thread exiting with uncaught exception (group=0x4001d800) 06-28 05:38:06.128: ERROR/AndroidRuntime(495): FATAL EXCEPTION: main java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example/com.example.HelloWorldActivity}: java.lang.IllegalArgumentException: http://www.w3.org/2001/XMLSchema at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2663) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679) at android.app.ActivityThread.access$2300(ActivityThread.java:125) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:123) at android.app.ActivityThread.main(ActivityThread.java:4627) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:521) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626) at dalvik.system.NativeStart.main(Native Method) Caused by: java.lang.IllegalArgumentException: http://www.w3.org/2001/XMLSchema at javax.xml.validation.SchemaFactory.newInstance(SchemaFactory.java:194) at com.example.HelloWorldActivity.onStart(HelloWorldActivity.java:26) at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1129) at android.app.Activity.performStart(Activity.java:3781) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2636) ... 11 more 

El Javadoc de SchemaFactory menciona “SchemaFactory por defecto de la plataforma se encuentra en una implementación específica. Debe haber una plataforma SchemaFactory predeterminada para el esquema XML del W3C”.

Tuve el mismo problema y leí muchas publicaciones antes de obtener una respuesta que funcionó para mí. La referencia a la constante no funcionará en Dalvik. Descubrí que tenía que modificar mi código para trabajar con el proyecto Xerces-for-Android y luego pude obtener la validación xml que estaba buscando. Lo más probable es lo que está haciendo con la referencia de variable. Los siguientes son detalles de la configuración y algunos ejemplos de código que muestran cómo obtener la validación para trabajar en Android.

Lo siguiente funcionó para mí:

  1. Crea una utilidad de validación
  2. Obtenga tanto el xml como el xsd en el archivo en el sistema operativo Android y use la utilidad de validación en su contra.
  3. Use Xerces-For-Android para hacer la validación.

Android admite algunos paquetes que podemos usar, creé mi utilidad de validación xml en base a: http://docs.oracle.com/javase/1.5.0/docs/api/javax/xml/validation/package-summary.html

Mi prueba inicial de sandbox fue bastante suave con Java, luego traté de dárselo a Dalvik y descubrí que mi código no funcionaba. Algunas cosas simplemente no son compatibles con Dalvik, así que hice algunas modificaciones.

Encontré una referencia a xerces para Android, así que modifiqué mi prueba de sandbox ( lo siguiente no funciona con android, el ejemplo después de esto ):

 import java.io.File; import javax.xml.XMLConstants; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.Source; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamSource; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import javax.xml.validation.Validator; import org.w3c.dom.Document; /** * A Utility to help with xml communication validation. */ public class XmlUtil { /** * Validation method. * Base code/example from: http://docs.oracle.com/javase/1.5.0/docs/api/javax/xml/validation/package-summary.html * * @param xmlFilePath The xml file we are trying to validate. * @param xmlSchemaFilePath The schema file we are using for the validation. This method assumes the schema file is valid. * @return True if valid, false if not valid or bad parse. */ public static boolean validate(String xmlFilePath, String xmlSchemaFilePath) { // parse an XML document into a DOM tree DocumentBuilder parser = null; Document document; // Try the validation, we assume that if there are any issues with the validation // process that the input is invalid. try { // validate the DOM tree parser = DocumentBuilderFactory.newInstance().newDocumentBuilder(); document = parser.parse(new File(xmlFilePath)); // create a SchemaFactory capable of understanding WXS schemas SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); // load a WXS schema, represented by a Schema instance Source schemaFile = new StreamSource(new File(xmlSchemaFilePath)); Schema schema = factory.newSchema(schemaFile); // create a Validator instance, which can be used to validate an instance document Validator validator = schema.newValidator(); validator.validate(new DOMSource(document)); } catch (Exception e) { // Catches: SAXException, ParserConfigurationException, and IOException. return false; } return true; } } 

El código anterior tenía que modificarse para que funcione con xerces para Android ( http://gc.codehum.com/p/xerces-for-android/ ). Necesita SVN para obtener el proyecto, las siguientes son algunas notas de cuna:

 download xerces-for-android download silk svn (for windows users) from http://www.sliksvn.com/en/download install silk svn (I did complete install) Once the install is complete, you should have svn in your system path. Test by typing "svn" from the command line. I went to my desktop then downloaded the xerces project by: svn checkout http://xerces-for-android.googlecode.com/svn/trunk/ xerces-for-android-read-only You should then have a new folder on your desktop called xerces-for-android-read-only 

Con el contenedor anterior (eventualmente lo convertiré en un contenedor, simplemente lo copié directamente en mi fuente para realizar pruebas rápidas. Si desea hacer lo mismo, puede hacer el contenedor rápidamente con Ant ( http: //ant.apache) .org / manual / using.html )), pude obtener lo siguiente para trabajar para mi validación xml:

 import java.io.File; import java.io.IOException; import mf.javax.xml.transform.Source; import mf.javax.xml.transform.stream.StreamSource; import mf.javax.xml.validation.Schema; import mf.javax.xml.validation.SchemaFactory; import mf.javax.xml.validation.Validator; import mf.org.apache.xerces.jaxp.validation.XMLSchemaFactory; import org.xml.sax.SAXException; /** * A Utility to help with xml communication validation. */public class XmlUtil { /** * Validation method. * * @param xmlFilePath The xml file we are trying to validate. * @param xmlSchemaFilePath The schema file we are using for the validation. This method assumes the schema file is valid. * @return True if valid, false if not valid or bad parse or exception/error during parse. */ public static boolean validate(String xmlFilePath, String xmlSchemaFilePath) { // Try the validation, we assume that if there are any issues with the validation // process that the input is invalid. try { SchemaFactory factory = new XMLSchemaFactory(); Source schemaFile = new StreamSource(new File(xmlSchemaFilePath)); Source xmlSource = new StreamSource(new File(xmlFilePath)); Schema schema = factory.newSchema(schemaFile); Validator validator = schema.newValidator(); validator.validate(xmlSource); } catch (SAXException e) { return false; } catch (IOException e) { return false; } catch (Exception e) { // Catches everything beyond: SAXException, and IOException. e.printStackTrace(); return false; } catch (Error e) { // Needed this for debugging when I was having issues with my 1st set of code. e.printStackTrace(); return false; } return true; } } 

Algunas notas secundarias:

Para crear los archivos, hice una sencilla utilidad de archivos para escribir cadenas en los archivos:

 public static void createFileFromString(String fileText, String fileName) { try { File file = new File(fileName); BufferedWriter output = new BufferedWriter(new FileWriter(file)); output.write(fileText); output.close(); } catch ( IOException e ) { e.printStackTrace(); } } 

También necesitaba escribir en un área a la que tenía acceso, así que hice uso de:

 String path = this.getActivity().getPackageManager().getPackageInfo(getPackageName(), 0).applicationInfo.dataDir; 

Un poco hackish, funciona. Estoy seguro de que hay una manera más sucinta de hacerlo, sin embargo, pensé que compartiría mi éxito, ya que no había ningún buen ejemplo que encontrara.

Es posible que tenga un poco de suerte volver a empaquetar xerces con jarjar y luego pasar

 "org.apache.xerces.jaxp.validation.XMLSchemaFactory" 

a

 SchemaFactory.newInstance(String schemaLanguage, String factoryClassName, ClassLoader classLoader) 

si estás utilizando API> = 9 o directamente creando instancias

 org.apache.xerces.jaxp.validation.XMLSchemaFactory 

si está utilizando API 8. Puede que no funcione en absoluto con una API anterior.