Search code examples
javaxmlxsdsaxstrategy-pattern

Java SAX strategy pattern based on XSD value


How can I implement a strategy pattern upon SAX based upon the XSD definition?

like:
if xsd = V1 use V1Parser
if xsd = V2 use V2Parser
if xsd = V3 use V3Parser
else error

The problem is i have to peek into the XML to know which XSD is defined but then I am not able to change the Parser anymore (and I won't begin again because the xsd is defined not at the beginning / not well formated XML from ERM system).

Do you know a workaround?


Solution

  • The solution could be to use a DefaultHandler VDispatch which internally delegates the SAX events to the appropriate DefaultHandler V1, V2 or V3.

    In startElement VDispatch looks for the beginning of a relevant subtree. Depending on the subtrees XSD it chooses the corresponding handler V1, V2, or V3.

    Inside the subtree it forwards all events to that chosen handler.

    Outside the subtree it ignores all events.

    public class VDispatch extends DefaultHandler {
         private DefaultHandler current_;
         private int subtreeLevel_;
    
         public void startElement(String uri, String localName, String qName, Attributes attributes) {
              if ((current_ == null) && (subtree-is-starting)) {
                  current_ = select-handler-based-on-xsd;
                  subtreeLevel_ = 0;
              }
              if (current_ != null) {
                  current_.startElement(uri, localName, qName, attributes);
                  subtreeLevel_++;
              }
         }
    
         public void endElement(String uri, String localName, String qName) {
              if (current_ != null) {
                  current_.endElement(uri, localName, qName);
                  if (--subtreeLevel_ == 0)
                      current_ = null;
              }
         }
    
         // simple forwarding in all other DefaultHandler methods
         public void characters(char[] ch, int start, int length) {
              if (current_ != null)
                  current_.characters(ch, start, length);
         }
    }