android with commons-digester java.lang.UnsupportedOperationException:此解析器不支持规范"Unknown"版本"0.0"



我必须使用commons-digucher.jar来处理android中的xml文件事实上,这是一个开源程序,它使用commons-digital.jar在Java中进行xml处理我需要更改它以支持Android但是这个错误发生了:

Digester.getParser:java.lang.UnsupportedOperationException:此解析器不支持规范"未知"版本"0.0"

java.lang.NullPointerException03-29 11:24:02.590:W/System.err(17018):位于org.apache.commons.Digester.getXMLReader(Digester.java:790)03-29 11:24:02.590:W/System.err(17018):在org.apache.commons.Digester.parse上(Digester.java:1588)03-29 11:24:02.590:W/System.err(17018):在org.apache.commons.Digester.parse上(Digester.java:1557)03-29 11:24:02.590:W/System.err(17018):访问com.tashkeel.android.putilities.alkhalil.DbLoader.LoadPrefixes(DbLoader.java:65)03-29 11:24:02.590:W/System.err(17018):访问com.tashkeel.android.utilities.alkhalil.Analyzer.(Analyzer.java:64)03-29 11:24:02.600:W/System.err(17018):在com.tashkeel.android.MainActivity$1.run(MainActivity.java:80)03-29 11:24:02.600:W/System.err(17018):在java.lang.Thread.run(Thread.java:856)03-29 11:24:03.240:W/系统错误(17018):

以及使用公共消化器的代码示例

 Digester digester = new Digester();
 digester.addObjectCreate("prefixes", Lists.class);
 digester.addObjectCreate("prefixes/prefixe", Prefixe.class);
  digester.addSetProperties("prefixes/prefixe", "unvoweledform",     
           "unvoweledform");
 digester.addSetProperties("prefixes/prefixe", "voweledform",
  "voweledform");
  digester.addSetProperties("prefixes/prefixe", "desc", "desc");
 digester.addSetProperties("prefixes/prefixe", "classe", "classe");
 digester.addSetNext("prefixes/prefixe", "addPrefixe");
 return (Lists)digester.parse(pref);

我试图解析的xml的一部分:

  <?xml version="1.0" encoding="utf-8" ?>
<prefixes>
    <prefixe unvoweledform="" voweledform="" desc="" classe="C1">
    </prefixe>
    <prefixe unvoweledform="و" voweledform="وَ" desc="حرف العطف" classe="C1">
        </prefixe>
    <prefixe unvoweledform="ف" voweledform="فَ" desc="حرف العطف أو الاستئناف" 
classe="C1">
     </prefixe>
    </prefixes>

查看Digester的源代码,它看起来是这样的代码:

SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware( namespaceAware );
factory.setXIncludeAware( xincludeAware );
factory.setValidating( validating );
factory.setSchema( schema );

然后检查SAXParserFactory的JavaDoc#setSchema:

解析器必须能够处理任何Schema实现。。。Throws:UnsupportedOperationException-当实现没有重写此方法。

因此,我猜测您的代码正在接收的SAXParserFactory实现在某种程度上不支持模式。

在SAXParserFactory.html#newInstance doco中有一些故障排除技巧,但您也可以找到返回的确切解析器类(不需要Digester代码):

SAXParserFactory factory = SAXParserFactory.newInstance();
System.err.println("SAXParserFactory class is " + factory.getClass().getName());

此外,从Android SAXParserFactory文档:

UnsupportedOperationException对于向后兼容性,当使用了早期版本的JAXP的实现,此异常将被抛出。

因此,您可能需要检查您正在使用的JAXP等的版本。

更新

假设您不需要模式,您可以尝试这种方法,它可能会起作用。。。与其让消化器为您创建SAXParserFactory,不如自己创建一个——这样您就可以避免调用setSchema,这看起来可能是个问题:

// create your own SAXParserFactory, but don't call any of the set methods unless you explicitly need to
final SAXParserFactory myfactory = SAXParserFactory.newInstance();
//myfactory.setNamespaceAware( namespaceAware );
//myfactory.setXIncludeAware( xincludeAware );
//myfactory.setValidating( validating );
//myfactory.setSchema( schema );
// create your own Digester and override the getFactory method to return your own factory
Digester digester = new Digester() {
  @Override
  public SAXParserFactory getFactory() {
    return myfactory;
  }
};
// use this digester as normal for the rest of your code...

目前没有进行任何android开发,所以无法测试,但看起来它可以工作。。。

更新2

因此,看起来它解决了模式问题,而您现在看到的似乎是一个单独的类加载器问题。这实际上是一个单独的问题,但这里有一个可能的破解。。。绕过banutils内省,只需使用自定义规则自己处理属性。这是非常实用的,因为您的示例中有相当简单的XML——任何比这更复杂的东西和这种方法都变得不可行:

final List<Prefixe> list = new ArrayList<>();
final SAXParserFactory factory = SAXParserFactory.newInstance();
Digester digester = new Digester() {
  @Override
  public SAXParserFactory getFactory() {
     System.out.println("using custom factory...");
    return factory;
  }
};
digester.addRule("prefixes/prefixe", new Rule() {
  @Override
  public void begin(String namespace, String name, Attributes attributes) throws Exception {
    Prefixe prefixe = new Prefixe();
    prefixe.setUnvoweledform(attributes.getValue("unvoweledform"));
    prefixe.setVoweledform(attributes.getValue("voweledform"));
    prefixe.setDesc(attributes.getValue("desc"));
    prefixe.setClasse(attributes.getValue("classe"));
    list.add(prefixe);
  }
});
digester.parse(...);

请注意,看起来你在某个地方有类加载器问题(除非你拥有的beanutils版本在某种程度上被削弱了?),我强烈建议你尝试找出这些问题的根源,因为它们可能会一次又一次地咬你。。。

祝你好运!

经过@Barney answer的一点修改后的最终答案要从函数返回列表,请在addRule函数中添加前缀:

    public Lists LoadPrefixes() throws Exception {
    InputStream   in = assetManager.open("db/prefixes.xml");
   final SAXParserFactory factory = SAXParserFactory.newInstance();
    Digester digester = new Digester() {
      @Override
      public SAXParserFactory getFactory() {
         //System.out.println("using custom factory...");
        return factory;
      }
    };
      final Lists Lists_ob=new Lists();

    digester.addRule("prefixes/prefixe", new Rule() {
      @Override
      public void begin(String namespace, String name, Attributes attributes) throws Exception {
        Prefixe prefixe = new Prefixe();
        prefixe.setUnvoweledform(attributes.getValue("unvoweledform"));
        prefixe.setVoweledform(attributes.getValue("voweledform"));
        prefixe.setDesc(attributes.getValue("desc"));
        prefixe.setClasse(attributes.getValue("classe"));
        Lists_ob.addPrefixe(prefixe);
      }
    });

      digester.parse(in);
     return Lists_ob;
}

这是代码最初在Lists.class 中

 private List prefixes = new LinkedList();
   public void addPrefixe(Prefixe p) {
    prefixes.add(p);
}