Typed Pull API for XML Schema Types Processing

What is it?

Simple to use API (and its implementation) to work with stream of XML events to convert between XSD types to Java types.

Features

Mapped Types

We have used as guideline to allow invertible mapping between XML Schema data types and Java types. We have computed intersection between Java and XSD types as we believe such invertible mapping is natural to use

This is table of invertible mappings: list of types that have XML Schema that has natural mapping in Java

Simple_Type

Java_Type

xsd:anyURI

java.net.URI

xsd:base64Binary

byte[]

xsd:boolean

boolean

xsd:byte

byte

xsd:decimal

java.math.BigDecimal

xsd:double

double

xsd:float

float

xsd:int

int

xsd:integer

java.math.BigInteger

xsd:long

long

xsd:QName

javax.xml.namespace.QName

xsd:short

short

xsd:string

java.lang.String

NOTE: We require J2SE 1.4 so java.net.URI is available and is natural mapping for anyUri.

We have decided to have no support sopenc:int and similar types defined in SOAP 1.1 Section 5 as theyare not in XSD. As for SOAP implementations we recommend to map soapenc:base64  to byte[] for reading but otherwise use base64Binary

Requiring reversible mappings we make sure that no information is lost during processing of XML messages. For example consider issue of nillable XML schema: in case when type such as xsd:int is used as parameter in RPC method wheat is value  if the parameters  is not present (minOccurs=0) should be represented as Integer and null passed? What if type is extended to be nillable and sent with  xsi:nil='1' in this case it would be also Java null value ...

Dealing With Additional XML Schema Types

The way we recommend to support additional types is to expose XML infoset to the XML processing code to allow applicaitin specific mapping.

Reading And Writing API

This is translation of previous section requirements into set of methods. We support reading and writing of element content and attribute values.

Type Pulled Parsing

Provide XML parsing functionality by extending XmlPullParser interface and add methods to do read and convert XML events into Java types

Here is the list of methods for xsd:double.

public interface XsdTypePullParser extends XmlPullParserWrapper {
    public static final String XSI_NS = "http://www.w3.org/2001/XMLSchema-instance";
    public static final String XSD_NS = "http://www.w3.org/2001/XMLSchema";

    public double nextXsdDoubleElement(String namesapxe, String name)
        throws XmlPullParserException, IOException, XsdException;
    public double readXsdDoubleElement() // reads text between START_TAG, END_TAG
        throws XmlPullParserException, IOException;
    public double readXsdDoubleAttribute(String name)
        throws XmlPullParserException, IOException;
    public double readXsdDoubleAttribute(String namespace, String name)
        throws XmlPullParserException, IOException;

We have given to functions name of corresponding XSD type such as for xsd:double it is  readXsdDouble() (instead of readDouble) to emphasize that it follow XSD rules and not Java types!

When processing XML it may be necessary to check xsi:type. However accessing xsi:type has performance overhead. Therefore above functions do not check for xsi:type. One way to deal with it would be to define set of additonal functions that check xsi:type:

    public double readDoubleCheckXsiType()
        throws XmlPullParserException, IOException;
 

However we think this is not necessary and be better done by utility function working directly on XML infoset such as

    public boolean checkXsiType(String namesapce, String name)
        throws XmlPullParserException, IOException;
    public boolean checkXsiTypeXsd(String nameOfXsdType)
 

We have no used QName for case when there is pair for (namespace, name) as-the prefix is irrelevant when checking (if necessary additional methods can be added in future to take QName)

CONSIDER: dealing with mixed content but use directly converting methods - obtain text content as String and convert it...

CONSIDER: adding xsd:sequence processing for primitive types like int[]

 

Example:

    double value = pp.readXsdDouble();
    double value = pp.readXsdDoubleAttribute("fooattrib");

XSD Typed Push Output

Thos method are used ot write element contnet and attributes that are consistent with XML Schema data types:

public interface XsdTypeSerializer extends XmlSerializerWrapper {
    public void writeXsdDouble(double d)
        throws XmlPullParserException, IOException, IllegalArgumentException;
    public void writeXsdDoubleElement(String namespace, String name, double d)
        throws XmlPullParserException, IOException, IllegalArgumentException;
    public void writeXsdDoubleElement(String namespace, String name, double d, boolean addXsiType)
        throws XmlPullParserException, IOException, IllegalArgumentException;
    public void writeXsdDoubleAttribute(String name, double d)
        throws XmlPullParserException, IOException, IllegalArgumentException;
    public void writeXsdDoubleAttribute(String namespace, String name, double d)
        throws XmlPullParserException, IOException, IllegalArgumentException;

Parameter addXsitType is used to indicate that xsi:type attribute should be written

NOTE: instead of boolean addXsitType we could have setUseXsiType(boolean) but then user code could easily mess up as code to write XML is typically recursively structured and one method could change setXsiType(boolean) affecting all other parts of code. By using addXsitType parameter we avoid need to check isXsiType() in each method and/or restore it to previous value.

NOTE: all namespace - prefix mapping etc. is taken care by XmlSerializer

Example:

    xs.writeDoubleElement("", "price", 100.0);
    xs.startTag("", "price");
    xs.writeDoubleElementAttribute("price", 100.0);


 Aleksander Slominski  Valid XHTML 1.0!