31 votes

SchemaFactory ne prend pas en charge le schéma XML W3C dans le niveau de plate-forme 8?

Avec le SDK Android, le code suivant dans une plaine vide Activité échoue:

@Override
protected void onStart() {
    super.onStart();

    SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
}

Le 2.2 émulateur logcat montre cette exception:

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

La Javadoc de SchemaFactory mentionne "la Plate-forme par défaut SchemaFactory est situé dans une mise en œuvre spécifique. Il doit y avoir une plate-forme par défaut SchemaFactory pour le W3C XML Schema".

3voto

VenomFangs Points 2222

J'ai eu le même problème et lu de nombreux messages avant j'ai eu une réponse qui a fonctionné pour moi. La référence à la constante ne fonctionne pas sur Dalvik. J'ai trouvé, j'ai dû modifier mon code pour travailler avec la Xerces-pour-Android projet, puis j'ai été en mesure d'obtenir la validation du xml je recherchais. Qui est probablement ce que vous faites par la variable de référence. Voici les détails de l'installation et un exemple de code montrant comment obtenir la validation de travailler sur android.

Le suivant a fonctionné pour moi:

  1. Créer un utilitaire de validation.
  2. Obtenir à la fois le xml et xsd dans un fichier sur le système d'exploitation android et utiliser l'utilitaire de validation contre elle.
  3. Utilisation Xerces-Pour-Android pour procéder à la validation.

Android prend en charge certains paquets que l'on peut utiliser, j'ai créé mon xml utilitaire de validation basée sur: http://docs.oracle.com/javase/1.5.0/docs/api/javax/xml/validation/package-summary.html

Ma première sandbox test était assez lisse avec java, puis j'ai essayé de port à Dalvik et constaté que mon code ne fonctionne pas. Certaines choses ne sont pas pris en charge de même avec Dalvik, j'ai donc fait quelques modifications.

J'ai trouvé une référence à xerces pour android, j'ai donc modifié mon bac à sable test de (la suite ne fonctionne pas avec android, l'exemple après ce n'):

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

Le code ci-dessus, a dû être modifié certains à travailler avec xerces pour android (http://gc.codehum.com/p/xerces-for-android/). Vous avez besoin SVN du projet, les éléments suivants sont quelques-crèche notes:

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

Avec le au-dessus de la fiole (Finalement je vais faire dans un bocal, juste copié directement dans mon source pour des tests rapides. Si vous souhaitez faire de même, vous pouvez faire le pot rapidement avec Ant (http://ant.apache.org/manual/using.html)), j'ai été en mesure d'obtenir la suite de travailler pour ma validation 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;
    }
}

Quelques Remarques:

Pour la création des fichiers, j'ai fait un simple fichier utilitaire pour écrire chaîne de fichiers:

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();
    }
}

J'ai aussi besoin de l'écrire pour une zone que j'ai eu accès, alors j'ai fait usage de:

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

Un peu hackish, il fonctionne. Je suis sûr qu'il y est une nouvelle façon de faire cela, cependant j'ai pensé que je vous ferais partager mon succès, comme il n'y avait pas de bons exemples que j'ai trouvé.

1voto

Avi Cherry Points 817

Vous pourriez avoir de la chance de reconditionner des xerces avec jarjar puis de passer

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

à

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

si vous utilisez une API> = 9 ou instanciez directement

 org.apache.xerces.jaxp.validation.XMLSchemaFactory 
 

si vous utilisez l'API 8. Cela pourrait ne pas fonctionner du tout en utilisant une API plus ancienne que celle-là.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X