Class SyntheticXMLReader

  • All Implemented Interfaces:
    Direct Known Subclasses:

    public abstract class SyntheticXMLReader
    extends Object
    implements XMLReader
    Base class implementing the tedious parts of a SAX XMLReader whose XML content is synthesized on the fly.

    An implementing class provides parse(InputSource) (which might do as little as ignoring its argument and calling super.parse()), and the workhorse next(), which should return an SyntheticXMLReader.EventCarrier on every call, then null when no parse events remain. An EventCarrier is a closure that can disgorge one or more SAX events onto SAX handlers (provided by this framework) when its toSAX() method is called. Start- and end-document events are synthesized here, so only the events in between should be generated by EventCarriers.

    An implementing class could return a single EventCarrier that will provide all of the XML content, or a sequence of EventCarriers each supplying one event or more, at the discretion of the implementor; if the content might be large or complex to generate, breaking it into multiple EventCarriers can provide a StAX-like ability to pull it in smaller pieces.

    This odd hybrid based on SAX is used, rather than simply basing a synthetic XML source directly on StAX, because of the numerous bugs in the Java runtime's implementation of StAX-to-TRAX bridging. Those are not so much in StAX itself (a tidy API), nor in the TRAX transformer implementations, but in the JRE classes added to bridge the two when StAX was added. The worst are in the handling of XML 'content' fragments, which are explicitly permitted by SQL/XML. A look at the bridge classes' code does not show a complete lack of attention to that case, but the code is broken and, after so many years, will probably not have its behavior changed. Because the java.sql.SQLXML API is expressly designed to allow easily obtaining a default Source to pass to a TRAX transformation, and to handle SQL/XML content that can be fragmentary, it follows that the default flavor of Source to return (and to implement synthetically here) must not be StAX. SAX is well supported and plays well with TRAX, even for content fragments.