简体   繁体   English

SchemaFactory 不支持平台级别 8 中的 W3C XML Schema?

[英]SchemaFactory doesn't support W3C XML Schema in platform level 8?

With the Android SDK, the following code in a plain empty Activity fails:使用 Android SDK,纯空 Activity 中的以下代码会失败:

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

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

The 2.2 emulator logcat shows this exception: 2.2 模拟器 logcat 显示此异常:

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

The Javadoc of SchemaFactory mentions "Platform default SchemaFactory is located in a implementation specific way. There must be a platform default SchemaFactory for W3C XML Schema." SchemaFactory 的 Javadoc提到“平台默认 SchemaFactory 以特定于实现的方式定位。W3C XML Schema 必须有一个平台默认 SchemaFactory。”

I had the same problem and read many posts before I got an answer that worked for me.在得到对我有用的答案之前,我遇到了同样的问题并阅读了很多帖子。 The reference to the constant won't work on Dalvik.对常量的引用在 Dalvik 上不起作用。 I found I had to modify my code to work with the Xerces-for-Android project then I was able to get the xml validation I was after.我发现我必须修改我的代码才能使用 Xerces-for-Android 项目,然后我才能获得我所追求的 xml 验证。 Which is most likely what you are doing by the variable reference.这很可能是您通过变量引用所做的事情。 The following are details of the setup and some example code showing how to get the validation to work on android.以下是设置的详细信息和一些示例代码,展示了如何让验证在 android 上运行。

The following worked for me:以下对我有用:

  1. Create a validation utility.创建验证实用程序。
  2. Get both the xml and xsd into file on the android OS and use the validation utility against it.将 xml 和 xsd 都放入 android 操作系统上的文件中,并针对它使用验证实用程序。
  3. Use Xerces-For-Android to do the validation.使用 Xerces-For-Android 进行验证。

Android does support some packages which we can use, I created my xml validation utility based on: http://docs.oracle.com/javase/1.5.0/docs/api/javax/xml/validation/package-summary.html Android确实支持我们可以使用的一些包,我创建了我的xml验证实用程序,基于: http ://docs.oracle.com/javase/1.5.0/docs/api/javax/xml/validation/package-summary.html

My initial sandbox testing was pretty smooth with java, then I tried to port it over to Dalvik and found that my code did not work.我最初的沙盒测试使用 java 非常顺利,然后我尝试将其移植到 Dalvik 并发现我的代码不起作用。 Some things just aren't supported the same with Dalvik, so I made some modifications. Dalvik 不支持某些东西,所以我做了一些修改。

I found a reference to xerces for android, so I modified my sandbox test of ( the following doesn't work with android, the example after this does ):我找到了对 android 的 xerces 的引用,所以我修改了我的沙盒测试(以下不适用于 android,之后的示例可以):

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

The above code had to be modified some to work with xerces for android ( http://gc.codehum.com/p/xerces-for-android/ ).上面的代码必须进行一些修改才能与 xerces for android ( http://gc.codehum.com/p/xerces-for-android/ ) 一起使用。 You need SVN to get the project, the following are some crib notes:你需要SVN来获取项目,以下是一些婴儿床笔记:

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

With the above jar (Eventually I'll make it into a jar, just copied it directly into my source for quick testing. If you wish to do the same, you can making the jar quickly with Ant ( http://ant.apache.org/manual/using.html )), I was able to get the following to work for my xml validation:使用上面的jar(最终我会把它做成一个jar,直接将它复制到我的源代码中以便快速测试。如果你想这样做,你可以用Ant快速制作jar( http://ant.apache .org/manual/using.html )),我能够获得以下内容来进行我的 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;
    }
}

Some Side Notes:一些旁注:

For creating the files, I made a simple file utility to write string to files:为了创建文件,我制作了一个简单的文件实用程序来将字符串写入文件:

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

I also needed to write to an area that I had access to, so I made use of:我还需要写一个我可以访问的区域,所以我使用了:

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

A little hackish, it works.有点hackish,它有效。 I'm sure there is a more succinct way of doing this, however I figured I'd share my success, as there weren't any good examples that I found.我确信有一种更简洁的方法可以做到这一点,但是我想我会分享我的成功,因为我没有找到任何好的例子。

You might have some luck re-packaging xerces with jarjar and then passing你可能有一些运气用 jarjar 重新包装 xerces 然后通过

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

to

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

if you're using API >=9 or directly instantiating如果您使用 API >=9 或直接实例化

org.apache.xerces.jaxp.validation.XMLSchemaFactory 

if you're using API 8. It might not work at all using an older API than that.如果您使用的是 API 8。使用比这更旧的 API 可能根本不起作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM