Simple to use API (and its implementation) to work with stream of XML events to convert between XSD types to Java 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 ...
The way we recommend to support additional types is to expose XML infoset to the XML processing code to allow applicaitin specific mapping.
This is translation of previous section requirements into set of methods. We support reading and writing of element content and attribute values.
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");
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);