Question

I'm trying to parse the XML from the Google Contacts API. The parts that are relevant to me and to this question are the given name, family name and the email address, and they look like this:

<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:gd="http://schemas.google.com/g/2005">
<entry>
  <gd:name>
    <gd:fullName>John Doe</gd:fullName>
    <gd:givenName>John</gd:givenName>
    <gd:familyName>Doe</gd:familyName>
  </gd:name>
  <gd:email rel="http://schemas.google.com/g/2005#work" address="john.doe@example.org" primary="true"/>
</entry>
<entry>
  <gd:name>
    <gd:fullName>Jane Smith</gd:fullName>
    <gd:givenName>Jane</gd:givenName>
    <gd:familyName>Smith</gd:familyName>
  </gd:name>
  <gd:email rel="http://schemas.google.com/g/2005#work" address="jane.smith@foo.bar" primary="true"/>
</entry>
</feed>

My digester class looks like this:

public class GmailContactsDigester {
  private Digester digester;

  public GmailContactsDigester() {
    digester = new Digester();
    digester.addObjectCreate("feed", ArrayList.class);
    digester.addObjectCreate("feed/entry", GoogleContact.class);
    digester.addBeanPropertySetter("feed/entry/gd:name/gd:givenName", "givenName");
    digester.addBeanPropertySetter("feed/entry/gd:name/gd:familyName", "familyName");
    digester.addRule("feed/entry/gd:email/", new SetPropertiesRule("address", "email"));
    digester.addSetNext("feed/entry", "add");
  }

  public List<GoogleContact> parse(InputStream xmlStream) {
    try {
      return (List<GoogleContact>) digester.parse(xmlStream);
    } catch (IOException e) {
      throw new RuntimeException(e);
    } catch (SAXException e) {
      throw new RuntimeException(e);
    }
  }
}

and the GoogleContact class is just my little domain object with the required fields and setters.

This all works just fine, but is dependent on the namespace prefix used in the XML. I'd like it to work regardless of the namespace, just by the element local names. How do I do that? I have tried various syntaxes for the patterns in the bean property setters, like "feed/entry/*:email" and "feed/entry/email", but they are not doing the trick.

Was it helpful?

Solution

The solution was to make the Digester namespace aware and to make the rule matching ignore the namespace:

public GmailContactsDigester() {
  digester = new Digester();
  digester.setRuleNamespaceURI(null);
  digester.setNamespaceAware(true);
  digester.addObjectCreate("feed", ArrayList.class);
  digester.addObjectCreate("feed/entry", GoogleContact.class);
  digester.addBeanPropertySetter("feed/entry/name/givenName");
  digester.addBeanPropertySetter("feed/entry/name/familyName");
  digester.addRule("feed/entry/email/", new SetPropertiesRule("address", "email"));
  digester.addSetNext("feed/entry", "add");
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top