android with commons-digester java.lang.UnsupportedOperationException: 此解析器不支持规范 "Unknown" 版本“0.0”
android with commons-digester java.lang.UnsupportedOperationException: This parser does not support specification "Unknown" version "0.0"
我必须使用 commons-digester.jar 来处理 xml 中的文件 android
实际上这是一个开源程序,它使用 commons-digester.jar 在 Java 中进行 xml 处理
我需要更改它以支持 Android
但是发生了这个错误:
Digester.getParser:
java.lang.UnsupportedOperationException: 此解析器不支持规范 "Unknown" 版本“0.0”
java.lang.NullPointerException
03-2911:24:02.590:
W/System.err(17018): 在 org.apache.commons.digester3.Digester.getXMLReader(Digester.java:790)
03-29 11:24:02.590: W/System.err(17018): 在 org.apache.commons.digester3.Digester.parse(Digester.java:1588)
03-29 11:24:02.590: W/System.err(17018): 在 org.apache.commons.digester3.Digester.parse(Digester.java:1557)
03-29 11:24:02.590: W/System.err(17018): 在 com.tashkeel.android.utilities.alkhalil.DbLoader.LoadPrefixes(DbLoader.java:65)
03-29 11:24:02.590: W/System.err(17018): 在 com.tashkeel.android.utilities.alkhalil.analyse.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/System.err(17018):
和使用 commons-digester 的代码示例
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 );
然后在 JavaDoc 中检查 SAXParserFactory#setSchema:
A parser must be able to work with any Schema implementation...
Throws: UnsupportedOperationException - When implementation does not
override this method.
所以我的猜测是 SAXParserFactory
您的代码接收的实现在某种程度上不支持模式。
SAXParserFactory.html#newInstance doco 中有一些故障排除提示,但您也可以找到返回的确切解析器 class 以及以下内容(不需要 Digester 代码):
SAXParserFactory factory = SAXParserFactory.newInstance();
System.err.println("SAXParserFactory class is " + factory.getClass().getName());
此外,来自 Android SAXParserFactory doco:
UnsupportedOperationException For backward compatibility, when
implementations for earlier versions of JAXP is used, this exception
will be thrown.
因此您可能需要检查您正在使用的 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
看起来它解决了架构问题,而您现在遇到的似乎是一个单独的 class 加载程序问题。这实际上是一个单独的问题,但这里有一个可能的黑客攻击......绕过 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(...);
请注意,您似乎在某处遇到了 classloader 问题(除非您使用的 beanutils 版本在某种程度上已被削弱?)我强烈建议您尝试查明真相因为它们可能会一次又一次地回来咬你...
祝你好运!
@Barney 回答稍作修改后的最终答案
使函数返回的列表在 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);
}
我必须使用 commons-digester.jar 来处理 xml 中的文件 android 实际上这是一个开源程序,它使用 commons-digester.jar 在 Java 中进行 xml 处理 我需要更改它以支持 Android 但是发生了这个错误:
Digester.getParser: java.lang.UnsupportedOperationException: 此解析器不支持规范 "Unknown" 版本“0.0”
java.lang.NullPointerException 03-2911:24:02.590: W/System.err(17018): 在 org.apache.commons.digester3.Digester.getXMLReader(Digester.java:790) 03-29 11:24:02.590: W/System.err(17018): 在 org.apache.commons.digester3.Digester.parse(Digester.java:1588) 03-29 11:24:02.590: W/System.err(17018): 在 org.apache.commons.digester3.Digester.parse(Digester.java:1557) 03-29 11:24:02.590: W/System.err(17018): 在 com.tashkeel.android.utilities.alkhalil.DbLoader.LoadPrefixes(DbLoader.java:65) 03-29 11:24:02.590: W/System.err(17018): 在 com.tashkeel.android.utilities.alkhalil.analyse.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/System.err(17018):
和使用 commons-digester 的代码示例
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 );
然后在 JavaDoc 中检查 SAXParserFactory#setSchema:
A parser must be able to work with any Schema implementation... Throws: UnsupportedOperationException - When implementation does not override this method.
所以我的猜测是 SAXParserFactory
您的代码接收的实现在某种程度上不支持模式。
SAXParserFactory.html#newInstance doco 中有一些故障排除提示,但您也可以找到返回的确切解析器 class 以及以下内容(不需要 Digester 代码):
SAXParserFactory factory = SAXParserFactory.newInstance();
System.err.println("SAXParserFactory class is " + factory.getClass().getName());
此外,来自 Android SAXParserFactory doco:
UnsupportedOperationException For backward compatibility, when implementations for earlier versions of JAXP is used, this exception will be thrown.
因此您可能需要检查您正在使用的 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
看起来它解决了架构问题,而您现在遇到的似乎是一个单独的 class 加载程序问题。这实际上是一个单独的问题,但这里有一个可能的黑客攻击......绕过 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(...);
请注意,您似乎在某处遇到了 classloader 问题(除非您使用的 beanutils 版本在某种程度上已被削弱?)我强烈建议您尝试查明真相因为它们可能会一次又一次地回来咬你...
祝你好运!
@Barney 回答稍作修改后的最终答案 使函数返回的列表在 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);
}