2

I have to use commons-digester.jar for processing xml files in android actually this was open source program that uses commons-digester.jar for xml processing in Java and I need to change it to support Android but this error happens :

Digester.getParser: java.lang.UnsupportedOperationException: This parser does not support specification "Unknown" version "0.0"

java.lang.NullPointerException 03-29 11:24:02.590: W/System.err(17018): at org.apache.commons.digester3.Digester.getXMLReader(Digester.java:790) 03-29 11:24:02.590: W/System.err(17018): at org.apache.commons.digester3.Digester.parse(Digester.java:1588) 03-29 11:24:02.590: W/System.err(17018): at org.apache.commons.digester3.Digester.parse(Digester.java:1557) 03-29 11:24:02.590: W/System.err(17018): at com.tashkeel.android.utilities.alkhalil.DbLoader.LoadPrefixes(DbLoader.java:65) 03-29 11:24:02.590: W/System.err(17018): at com.tashkeel.android.utilities.alkhalil.analyse.Analyzer.(Analyzer.java:64) 03-29 11:24:02.600: W/System.err(17018): at com.tashkeel.android.MainActivity$1.run(MainActivity.java:80) 03-29 11:24:02.600: W/System.err(17018): at java.lang.Thread.run(Thread.java:856) 03-29 11:24:03.240: W/System.err(17018):

and sample of code that uses 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);

part of xml that I try to parse :

  <?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>
  • Could you post a small part of the XML you are trying to parse? In your code above you never call `digester.setXMLSchema(...)` - does that mean your XML has no namespace and does not care about schemas? – Barney Apr 05 '15 at 04:35
  • cool - added an update to my answer below which may help – Barney Apr 05 '15 at 04:50

2 Answers2

1

Looking at the source code for Digester, what it comes down to appears to be this code:

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

Then checking the JavaDoc for SAXParserFactory#setSchema:

A parser must be able to work with any Schema implementation... Throws: UnsupportedOperationException - When implementation does not override this method.

So my guess is the SAXParserFactory implementation your code is receiving does not support schemas in some way.

There are some tips for troubleshooting in the SAXParserFactory.html#newInstance doco, but you can also just find the exact parser class being returned with the following (no Digester code required):

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

Also, from the Android SAXParserFactory doco:

UnsupportedOperationException For backward compatibility, when implementations for earlier versions of JAXP is used, this exception will be thrown.

So you may want to check the versions of JAXP etc. you are using.

Update

Given that you do not need schemas, you can try this which may work... instead of letting the digester create the SAXParserFactory for you, create one yourself - that way you can avoid the call to setSchema which looks like it may be the problem:

// 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...

Not doing any android development at the moment so can't test this, but looks like it could work...

Update 2

So that looked like it fixed the schema problem, and what you have now appears to be a separate class loader issue. That's actually a separate question, but here's a possible hack... bypass the banutils introspection and just process the attributes yourself with a custom rule. This is only really practical because you have fairly simple XML in your example - anything more complicated that that and this approach becomes unworkable:

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

Please note that it looks like you have classloader issues somewhere (unless the version of beanutils you have has been crippled in some way?) and I'd strongly recommend you try to get to the bottom of those as they may come back to bite you again and again...

Good luck!

Barney
  • 2,786
  • 2
  • 32
  • 34
  • I really appreciate your effort for help . thanks so much . I tried SAXParserFactory factory = SAXParserFactory.newInstance(); System.err.println("SAXParserFactory class is " + factory.getClass().getName()); and found this"org.apache.harmony.xml.parsers.SAXParserFactoryImpl" and also found this old question http://stackoverflow.com/questions/6809683/jaxp-on-android/29453961#29453961 but it hasn't answer yet . and i will try other points in your answer . thanks – islam islam Apr 05 '15 at 04:09
  • i tried the updated answer but unfortunately it resulted for this error : Could not find class 'org.apache.commons.beanutils.MappedPropertyDescriptor', referenced from method org.apache.commons.beanutils.BeanUtilsBean.setProperty 04-05 06:58:10.362: E/dalvikvm(16121 and related errors but i already has the jar libraries commons-beanutils-1.8.3.jar commons-digester3-3.0.jar commons-logging-1.1.3.jar commons-collections-2.1.jar in the build paths . this error happened to me before when using old version of digester but after using digester 3 it didn't appear again except after this try – islam islam Apr 05 '15 at 05:08
  • Ok - so looks like the fix above fixed the schema problem, and you are now back to where you were previously with a beanutils problem? – Barney Apr 05 '15 at 05:17
  • yes , exactly this is my case now and i try now for solving it – islam islam Apr 05 '15 at 05:25
  • thank you so much , update 2 solved all my problems and classes dependency problems also gone . this is except that i needed a little bit modification for returned lists to make it add prefixes to fit my original code thanks so much @Barney – islam islam Apr 06 '15 at 22:39
  • @islam-islam no problem - glad we finally got there! Please consider marking the answer as accepted (the big green tick) if it solved your problem. Cheers. – Barney Apr 06 '15 at 23:15
  • i want this but the lack of reputations prevented me to mark the answer . – islam islam Apr 06 '15 at 23:30
  • @islam-islam strange - you need 15 rep to vote up an answer, but you should be able to accept an answer to your own question - http://meta.stackoverflow.com/questions/251078/how-to-update-and-accept-answers. Either way, not really important, and glad we solved your problem. – Barney Apr 06 '15 at 23:52
0

final answer after little bit modification from @Barney answer to make returned lists from the function add prefix inside addRule function :

    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;

}

and this is code was originally inside Lists.class

 private List prefixes = new LinkedList();

   public void addPrefixe(Prefixe p) {
    prefixes.add(p);
}