Compiles a set of XSD and/or WSDL files into XMLBeans. This is useful for building an XMLBean JAR from XSD and WSDL files. If desired, the task can also generate the source code that makes up the XMLBean type system specified by the schema files.
Note: This task depends on two external libraries not included in the Ant distribution: one called xbean.jar, one called jsr173_1.0_api.jar. Both can be found in the XMLBeans developer kit at http://xmlbeans.apache.org/. The build script will need to include a taskdef for xmlbean, which could look like this:
<taskdef name="xmlbean"
classname="org.apache.xmlbeans.impl.tool.XMLBean"
classpath="path/to/xbean.jar:path/to/jsr173_1.0_api.jar" />
It is possible to refine the set of files that are being processed. This can be done with the includes, includesfile, excludes, excludesfile and defaultexcludes attributes. With the includes or includesfile attribute you specify the files you want to have included by using patterns. The exclude or excludesfile attributes are used to specify the files you want to have excluded. This is also done with patterns. And finally with the defaultexcludes attribute, you can specify whether you want to use default exclusions or not. See the section on directory based tasks in the Ant documentation, on how the inclusion/exclusion of files works, and how to write patterns.
This task forms an implicit FileSet
and supports all attributes of <fileset>
(dir
becomes basedir
) as well as the nested <include>
,
<exclude>
and <patternset>
elements.
Attribute | Description | Required |
schema | A file that points to either an individual schema file or a directory of files. Not a path reference. If multiple schema files need to be built together, use a nested fileset instead of setting schema. | Yes, unless a fileset element is nested. |
destfile | Define the name of the jar file created. For instance, "myXMLBean.jar" will output the results of this task into a jar with the same name. | No, default is "xmltypes.jar". |
download | Set to true to permit the compiler to download URLs for
imports and includes. Defaults to false, meaning all imports and
includes must be copied locally. |
No, default is false. |
classgendir |
Set a location to generate CLASS files into. |
No |
srconly |
A value of true means that only source will be generated. |
No, default is false. |
srcgendir |
Set a location to generate JAVA files into. |
No |
javasource |
Generate java source compatible with the given
version. Currently only "1.4" and "1.5" are supported. |
No, Default is "1.4" |
classpath | The classpath to use if schemas in the fileset import definitions that are supplied by other compiled XMLBeans JAR files, or if JAVA files are in the schema fileset. Also supports a nested classpath. | No |
classpathref | Adds a classpath, given as reference to a path defined elsewhere. | No |
includes | Comma- or space-separated list of patterns of files that must be included. All files are included when omitted. | No |
includesfile | The name of a file. Each line of this file is taken to be an include pattern. | No |
excludes | Comma- or space-separated list of patterns of files that must be excluded. No files (except default excludes) are excluded when omitted. | No |
excludesfile | The name of a file. Each line of this file is taken to be an exclude pattern. | No |
defaultexcludes | Indicates whether default excludes should be used or not ("yes"/"no"). Default excludes are used when omitted. | No |
debug | Indicates whether source should be compiled with debug
information; defaults to off . If set to off ,
-g:none will be passed on the command line for compilers
that support it (for other compilers, no command line argument will
be used). If set to true , the value of the debuglevel
attribute determines the command line argument. |
No |
debuglevel | Keyword list to be appended to the -g command-line
switch. This will be ignored by all implementations except modern
and classic(ver >= 1.2) . Legal values are none
or a comma-separated list of the following keywords: lines ,
vars , and source . If debuglevel
is not specified, by default, nothing will be appended to -g .
If debug is not turned on, this attribute will be ignored.
|
No |
optimize | Indicates whether source should be compiled with optimization;
defaults to off . |
No |
includeAntRuntime | Whether to include the Ant run-time libraries in the
classpath; defaults to yes . |
No |
includeJavaRuntime | Whether to include the default run-time libraries from
the executing VM in the classpath; defaults to no . |
No |
fork | Whether to execute javac using the JDK compiler
externally; defaults to yes . |
No, default is true |
executable | Complete path to the javac executable to
use in case of fork="yes" . Defaults to the compiler
of the Java version that is currently running Ant. Ignored if fork="no" |
No |
memoryInitialSize | The initial size of the memory for the underlying VM,
if javac is run externally; ignored otherwise. Defaults
to the standard VM memory setting. (Examples: 83886080 ,
81920k , or 80m ) |
No |
memoryMaximumSize | The maximum size of the memory for the underlying VM,
if javac is run externally; ignored otherwise. Defaults
to the standard VM memory setting. (Examples: 83886080 ,
81920k , or 80m ) |
No |
compiler | The compiler implementation to use. If this attribute
is not set, the value of the build.compiler property, if
set, will be used. Otherwise, the default compiler for the current VM
will be used.
| No |
failonerror | Determines whether or not the ant target will continue
if the XMLBean creation encounters a build error. |
No, default is true. |
verbose |
Controls the amount of build message output. |
No, default is true. |
quiet |
Controls the amount of build message output. |
No, default is false. |
typesystemname |
The name of the package that the TypeSystemHolder class
should be generated in. Normally this should be left unspecified.
None of the XMLBeans are generated in this package. Use .xsdconfig files
to modify XMLBean package or class names. |
No |
noupa | Do not enforce the unique particle attribution rule. |
No, default is false. | nopvr | Do not enforce the particle valid (restriction) rule. |
No, default is false. |
noann | Skip over schema <annotation> elements |
No, default is false. |
nopvr | Do not validate the contents of schema <documentation> elements. |
No, default is false. |
ignoreDuplicatesInNamespaces | Comma separated list of one or more namespaces in which duplicate definitions are to be ignored. | No |
<taskdef name="xmlbean"
classname="org.apache.xmlbeans.impl.tool.XMLBean"
classpath="path/to/xbean.jar:path/to/jsr173_1.0_api.jar" />
The following builds all the schemas in the schemas directory and creates a jar called "Schemas.jar". (Note: both xbean.jar and jsr173_1.0_api.jar must be on the classpath when the task executes).
<xmlbean schema="schemas" destfile="Schemas.jar" classpath="path/to/xbean.jar:path/to/jsr173_1.0_api.jar" />The following compiles the schema "ourSchema.xsd" into the default jar "xmltypes.jar". If any imports and includes are defined by remote URLs, they are downloaded during the build.
<xmlbean schema="schemas/ourSchema.xsd" download="true"
classpath="path/to/xbean.jar:path/to/jsr173_1.0_api.jar" />
<xmlbean classgendir="${build.dir}" classpath="${class.path}"
failonerror="true">
<fileset basedir="src" excludes="**/*.xsd"/>
<fileset basedir="schemas" includes="**/*.*"/>
</xmlbean>
None.
XMLBeans provides intuitive ways to handle XML that make it easier for you to access and manipulate XML data and documents in Java.
Characteristics of XMLBeans approach to XML:
The starting point for XMLBeans is XML schema. A schema (contained in an XSD file) is an XML document that defines a set of rules to which other XML documents must conform. The XML Schema specification provides a rich data model that allows you to express sophisticated structure and constraints on your data. For example, an XML schema can enforce control over how data is ordered in a document, or constraints on particular values (for example, a birth date that must be later than 1900). Unfortunately, the ability to enforce rules like this is typically not available in Java without writing custom code. XMLBeans honors schema constraints.
Note: Where an XML schema defines rules for an XML document, an XML instance is an XML document that conforms to the schema.
You compile a schema (XSD) file to generate a set of Java interfaces that mirror the schema. With these types, you process XML instance documents that conform to the schema. You bind an XML instance document to these types; changes made through the Java interface change the underlying XML representation.
Previous options for handling XML include using XML programming interfaces (such as DOM or SAX) or an XML marshalling/binding tool (such as JAXB). Because it lacks strong schema-oriented typing, navigation in a DOM-oriented model is more tedious and requires an understanding of the complete object model. JAXB provides support for the XML schema specification, but handles only a subset of it; XMLBeans supports all of it. Also, by storing the data in memory as XML, XMLBeans is able to reduce the overhead of marshalling and demarshalling.
To get a glimpse of the kinds of things you can do with XMLBeans, take a look at an example using XML for a purchase order. The purchase order XML contains data exchanged by two parties, such as two companies. Both parties need to be able to rely on a consistent message shape, and a schema specifies the common ground.
Here's what a purchase order XML instance might look like.
<po:purchase-order xmlns:po="http://openuri.org/easypo"> <po:customer> <po:name>Gladys Kravitz</po:name> <po:address>Anytown, PA</po:address> </po:customer> <po:date>2003-01-07T14:16:00-05:00</po:date> <po:line-item> <po:description>Burnham's Celestial Handbook, Vol 1</po:description> <po:per-unit-ounces>5</po:per-unit-ounces> <po:price>21.79</po:price> <po:quantity>2</po:quantity> </po:line-item> <po:line-item> <po:description>Burnham's Celestial Handbook, Vol 2</po:description> <po:per-unit-ounces>5</po:per-unit-ounces> <po:price>19.89</po:price> <po:quantity>2</po:quantity> </po:line-item> <po:shipper> <po:name>ZipShip</po:name> <po:per-ounce-rate>0.74</po:per-ounce-rate> </po:shipper> </po:purchase-order>
This XML includes a root element, purchase-order, that has three kinds of child elements: customer, date, line-item, and shipper. An intuitive, object-based view of this XML would provide an object representing the purchase-order element, and it would have methods for getting the date and for getting subordinate objects for customer, line-item, and shipper elements. Each of the last three would have its own methods for getting the data inside them as well.
The following XML is the the schema for the preceding purchase order XML. It defines the XML's "shape" — what its elements are, what order they appear in, which are children of which, and so on.
<xs:schema targetNamespace="http://openuri.org/easypo" xmlns:po="http://openuri.org/easypo" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> <xs:element name="purchase-order"> <xs:complexType> <xs:sequence> <xs:element name="customer" type="po:customer"/> <xs:element name="date" type="xs:dateTime"/> <xs:element name="line-item" type="po:line-item" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="shipper" type="po:shipper" minOccurs="0"/> </xs:sequence> </xs:complexType> </xs:element> <xs:complexType name="customer"> <xs:sequence> <xs:element name="name" type="xs:string"/> <xs:element name="address" type="xs:string"/> </xs:sequence> </xs:complexType> <xs:complexType name="line-item"> <xs:sequence> <xs:element name="description" type="xs:string"/> <xs:element name="per-unit-ounces" type="xs:decimal"/> <xs:element name="price" type="xs:double"/> <xs:element name="quantity" type="xs:int"/> </xs:sequence> </xs:complexType> <xs:complexType name="shipper"> <xs:sequence> <xs:element name="name" type="xs:string"/> <xs:element name="per-ounce-rate" type="xs:decimal"/> </xs:sequence> </xs:complexType> </xs:schema>
This schema describes the purchase order XML instance by defining the following:
These are also global types. They are global because they are at the top level of the schema (in other words, just beneath the schema root element). This means that they may be referenced from anywhere else in the schema.
In other words, the schema defines types for the child elements and describes their position as subordinate to the root element, purchase-order.
When you use the XMLBean compiler with an XSD file such as this one, you generate a JAR file containing the interfaces generated from the schema.
With the XMLBeans interfaces in your application, you can write code that uses the new types to handle XML based on the schema. Here's an example that extracts information about each of the ordered items in the purchase order XML, counts the items, and calculates a total of their prices. In particular, look at the use of types generated from the schema and imported as part of the org.openuri.easypo package.
The printItems method receives a File object containing the purchase order XML file.
package docs.xmlbeans; import java.io.File; import org.apache.xmlbeans.*; import org.openuri.easypo.PurchaseOrderDocument; import org.openuri.easypo.PurchaseOrder; import org.openuri.easypo.LineItem; public class POHandler { public static void printItems(File po) throws Exception { /* * All XMLBeans schema types provide a nested Factory class you can * use to bind XML to the type, or to create new instances of the type. * Note that a "Document" type such as this one is an XMLBeans * construct for representing a global element. It provides a way * for you to get and set the contents of the entire element. * * Also, note that the parse method will only succeed if the * XML you're parsing appears to conform to the schema. */ PurchaseOrderDocument poDoc = PurchaseOrderDocument.Factory.parse(po); /* * The PurchaseOrder type represents the purchase-order element's * complex type. */ PurchaseOrder po = poDoc.getPurchaseOrder(); /* * When an element may occur more than once as a child element, * the schema compiler will generate methods that refer to an * array of that element. The line-item element is defined with * a maxOccurs attribute value of "unbounded", meaning that * it may occur as many times in an instance document as needed. * So there are methods such as getLineItemArray and setLineItemArray. */ LineItem[] lineitems = po.getLineItemArray(); System.out.println("Purchase order has " + lineitems.length + " line items."); double totalAmount = 0.0; int numberOfItems = 0; /* * Loop through the line-item elements, using generated accessors to * get values for child elements such a description, quantity, and * price. */ for (int j = 0; j < lineitems.length; j++) { System.out.println(" Line item: " + j); System.out.println( " Description: " + lineitems[j].getDescription()); System.out.println(" Quantity: " + lineitems[j].getQuantity()); System.out.println(" Price: " + lineitems[j].getPrice()); numberOfItems += lineitems[j].getQuantity(); totalAmount += lineitems[j].getPrice() * lineitems[j].getQuantity(); } System.out.println("Total items: " + numberOfItems); System.out.println("Total amount: " + totalAmount); } }
Notice that types generated from the schema reflect what's in the XML:
Capitalization and punctuation for generated type names follow Java convention. Also, while this example parses the XML from a file, other parse methods support a Java InputStream object, a Reader object, and so on.
The preceding Java code prints the following to the console:
Purchase order has 3 line items. Line item 0 Description: Burnham's Celestial Handbook, Vol 1 Quantity: 2 Price: 21.79 Line item 1 Description: Burnham's Celestial Handbook, Vol 2 Quantity: 2 Price: 19.89 Total items: 4 Total amount: 41.68
As you've seen XMLBeans provides a "factory" class you can use to create new instances. The following example creates a new purchase-order element and adds a customer child element. It then inserts name and address child elements, creating the elements and setting their values with a single call to their set methods.
public PurchaseOrderDocument createPO() { PurchaseOrderDocument newPODoc = PurchaseOrderDocument.Factory.newInstance(); PurchaseOrder newPO = newPODoc.addNewPurchaseOrder(); Customer newCustomer = newPO.addNewCustomer(); newCustomer.setName("Doris Kravitz"); newCustomer.setAddress("Bellflower, CA"); return newPODoc; }
The following is the XML that results. Note that XMLBeans assigns the correct namespace based on the schema, using an "ns1" (or, "namespace 1") prefix. For practical purposes, the prefix itself doesn't really matter — it's the namespace URI (http://openuri.org/easypo) that defines the namespace. The prefix is merely a marker that represents it.
<ns1:purchase-order xmlns:ns1="http://openuri.org/easypo"> <ns1:customer> <ns1:name>Doris Kravitz</ns1:name> <ns1:address>Bellflower, CA</ns1:address> </ns1:customer> </ns1:purchase-order>
Note that all types (including those generated from schema) inherit from XmlObject, and so provide a Factory class. For an overview of the type system in which XmlObject fits, see XMLBeans Support for Built-In Schema Types. For reference information, see XmlObject Interface.
The generated types you saw used in the preceding example are actually part of a hierarchy of XMLBeans types. This hierarchy is one of the ways in which XMLBeans presents an intuitive view of schema. At the top of the hierarchy is XmlObject, the base interface for XMLBeans types. Beneath this level, there are two main type categories: generated types that represent user-derived schema types, and included types that represent built-in schema types.
This topic has already introduced generated types. For more information, see Java Types Generated from User-Derived Schema Types.In addition to types generated from a given schema, XMLBeans provides 46 Java types that mirror the 46 built-in types defined by the XML schema specification. Where schema defines xs:string, xs:decimal, and xs:int, for example, XMLBeans provides XmlString, XmlDecimal, and XmlInt. Each of these also inherits from XmlObject, which corresponds to the built-in schema type xs:anyType.
XMLBeans provides a way for you to handle XML data as these built-in types. Where your schema includes an element whose type is, for example, xs:int, XMLBeans will provide a generated method designed to return an XmlInt. In addition, as you saw in the preceding example, for most types there will also be a method that returns a natural Java type such as int. The following two lines of code return the quantity element's value, but return it as different types.
// Methods that return simple types begin with an "x". XmlInt xmlQuantity = lineitems[j].xgetQuantity(); // Methods that return a natural Java type are unadorned. int javaQuantity = lineitems[j].getQuantity();
In a sense both get methods navigate to the quantity element; the getQuantity method goes a step further and converts the elements value to the most appropriate natural Java type before returning it. (XMLBeans also provides a means for validating the XML as you work with it.)
If you know a bit about XML schema, XMLBeans types should seem fairly intuitive. If you don't, you'll learn a lot by experimenting with XMLBeans using your own schemas and XML instances based on them.
For more information on the methods of types generated from schema, see Methods for Types Generated From Schema. For more about the how XMLBeans represents built-in schema types, see XMLBeans Support for Built-In Schema Types.
With XMLBeans you can use XQuery to query XML for specific pieces of data. XQuery is sometimes referred to as "SQL for XML" because it provides a mechanism to access data directly from XML documents, much as SQL provides a mechanism for accessing data in traditional databases.
XQuery borrows some of its syntax from XPath, a syntax for specifying nested data in XML. The following example returns all of the line-item elements whose price child elements have values less than or equal to 20.00:
PurchaseOrderDocument doc = PurchaseOrderDocument.Factory.parse(po); /* * The XQuery expression is the following two strings combined. They're * declared separately here for convenience. The first string declares * the namespace prefix that's used in the query expression; the second * declares the expression itself. */ String nsText = "declare namespace po = 'http://openuri.org/easypo'; "; String pathText = "$this/po:purchase-order/po:line-item[po:price <= 20.00]"; String queryText = nsText + pathText; XmlCursor itemCursor = doc.newCursor().execQuery(queryText); System.out.println(itemCursor.xmlText());
This code creates a new cursor at the start of the document. From there, it uses the XmlCursor interface's execQuery method to execute the query expression. In this example, the method's parameter is an XQuery expression that simply says, "From my current location, navigate through the purchase-order element and retrieve those line-item elements whose value is less than or equal to 20.00." The $this variable means "the current position."
For more information about XQuery, see XQuery 1.0: An XML Query Language at the W3C web site.
In the preceding example you may have noticed the XmlCursor interface. In addition to providing a way to execute XQuery expression, an XML cursors offers a fine-grained model for manipulating data. The XML cursor API, analogous to the DOM's object API, is simply a way to point at a particular piece of data. So, just like a cursor helps navigate through a word processing document, the XML cursor defines a location in XML where you can perform actions on the selected XML.
Cursors are ideal for moving through an XML document when there's no schema available. Once you've got the cursor at the location you're interested in, you can perform a variety of operations with it. For example, you can set and get values, insert and remove fragments of XML, copy fragments of XML to other parts of the document, and make other fine-grained changes to the XML document.
The following example uses an XML cursor to navigate to the customer element's name child element.
PurchaseOrderDocument doc = PurchaseOrderDocument.Factory.parse(po); XmlCursor cursor = doc.newCursor(); cursor.toFirstContentToken(); cursor.toFirstChildElement(); cursor.toFirstChildElement(); System.out.println(cursor.getText()); cursor.dispose();
What's happening here? As with the earlier example, the code loads the XML from a File object. After loading the document, the code creates a cursor at its beginning. Moving the cursor a few times takes it to the nested name element. Once there, the getText method retrieves the element's value.
This is just an introduction to XML cursors. For more information about using cursors, see Navigating XML with Cursors.
Note: The xbean.jar file that contains the XMLBeans library is fully functional as a standalone library.
Compiling schema for use with XMLBeans generates a kind of custom API specific to your schema. This API includes types with accessors designed to get and set parts of the XML defined by the schema. But if you've compiled schema that includes xs:any
particles, you may have noticed that XMLBeans doesn't generate accessors for these these particles.
For example, imagine the accessors generated by compiling the following schema snippet:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://xmlbeans.apache.org/samples/any" targetNamespace="http://xmlbeans.apache.org/samples/any" elementFormDefault="qualified"> <xs:element name="root"> <xs:complexType> <xs:sequence> <xs:element ref="stringelement"/> <xs:any processContents="lax"/> <xs:element name="arrayofany"> <xs:complexType> <xs:sequence> <xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="stringelement" type="xs:string"/> <xs:complexType name="ListOfStrings"> <xs:sequence> <xs:element ref="stringelement" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:attribute name="id" type="xs:string"/> </xs:complexType> </xs:schema>
After compilation, you'd have the follow methods for Root
, the type that gives you access to the <root>
element:
addNewArrayofany()
getArrayofany()
getStringelement()
setArrayofany(Arrayofany)
setStringelement(String)
xgetStringelement()
xsetStringelement(XmlString)
What's missing? There's no getAny
or setAny
. How do you get or set the <root>
element's second child? As it turns out, you do this by leaving behind (at least for a moment) JavaBeans-style accessors, and picking up any of a number of tools the API provides. These tools include:
XmlCursor
instances to "walk" the XML, handling elements cursor-style.selectPath
method to retrieve the XML you want via XPath.selectChildren
method to retrieve child elements by name.As described in Navigating XML with Cursors, with an XmlCursor
instance you can traverse your XML instance's full infoset. A cursor views XML as tokens, and you move a cursor from one token to another as if they were cars in a train.
The following example illustrates how you might, in the course of building out the <root>
document, create a second child element <anyfoo>
where schema specifies xs:any
. You add the element by creating it with a cursor, then (in lieu of a setter) using the XmlCursor.copyXml
or XmlCursor.moveXml
method to put the element where it needs to go.
// Start by creating a <root> element that will contain // the children built by this code. RootDocument rootDoc = RootDocument.Factory.newInstance(); RootDocument.Root root = rootDoc.addNewRoot(); // Add the first element, <stringelement>. root.setStringelement("some text"); // Create an XmlObject in which to build the second // element in the sequence, <anyfoo>. Here, the // XmlObject instance is simply a kind of incubator // for the XML. Later the XML will be moved into the // document this code is building. XmlObject anyFoo = XmlObject.Factory.newInstance(); // Add a cursor to do the work of building the XML. XmlCursor anyFooCursor = anyFoo.newCursor(); anyFooCursor.toNextToken(); // Add the element in the schema's namespace, then add // element content. anyFooCursor.beginElement(new QName(m_namespaceUri, "anyfoo")); anyFooCursor.insertChars("some text"); // Move the cursor back to the new element's top, where // it can grab all of the element's XML. anyFooCursor.toStartDoc(); anyFooCursor.toNextToken(); // Finally, move the XML into the <root> document by moving it // from a position at one cursor to a position at // another. XmlCursor rootCursor = root.newCursor(); rootCursor.toEndToken(); anyFooCursor.moveXml(rootCursor);
You might find that this build-and-move-cursor-to-cursor pattern is common when you're creating or moving XML when accessors aren't available. For example, you could do the same sort of thing when your schema defines a type that you want to place into an xs:any
space in an instance. The following code adds a <stringelement>
element as a child of the <arrayofany>
element, which schema defines as containing a sequence of xs:any
particles. The <stringlement>
element is simple, but it could just as easily be a complex schema type.
// Create a simple <stringelement>. StringelementDocument stringElementDoc = StringelementDocument.Factory.newInstance(); stringElementDoc.setStringelement("some text"); XmlCursor stringElementCursor = stringElementDoc.newCursor(); stringElementCursor.toFirstContentToken(); // Add a cursor to mark the position to which the new child // XML will be moved. XmlCursor arrayCursor = arrayOfAny.newCursor(); arrayCursor.toNextToken(); // Move the new <stringelement> into place. stringElementCursor.moveXml(arrayCursor); stringElementCursor.dispose();
XPath is a convenient, direct way to get at specific chunks of XML. In the XMLBeans API, you execute XPath expressions with the XmlObject.selectPath
or XmlCursor.selectPath
methods. The example in Java below assumes the following instance conforming to the schema introduced at the beginning of this topic:
<root xmlns="http://xmlbeans.apache.org/samples/any"> <stringelement>some text</stringelement> <anyfoo>some text</anyfoo> <arrayofany> <stringelement>some text</stringelement> <someelement> <stringlist id="001"> <stringelement>string1</stringelement> <stringelement>string2</stringelement> </stringlist> </someelement> </arrayofany> </root>
The following code uses XPath to reach the <stringelement>
element because there is no accessor available. It then shifts the XML around a little, moving <stringelement>
up in the hierarchy to replace its parent, <someelement>
.
public boolean editExistingDocWithSelectPath(RootDocument rootDoc) { String namespaceUri = "http://xmlbeans.apache.org/samples/any"; // Put a cursor at the top of the <arrayofany> element. XmlCursor selectionCursor = rootDoc.getRoot().getArrayofany().newCursor(); // Use XPath and cursor movement to position the cursor at // the <stringlist> element. String namespaceDecl = "declare namespace any='" + namespaceUri + "'; "; selectionCursor.selectPath(namespaceDecl + "$this//any:someelement/any:stringlist"); selectionCursor.toNextSelection(); // Create a new cursor at the same location and move it to // <stringelement>'s <someelement> parent. XmlCursor editCursor = selectionCursor.newCursor(); editCursor.toParent(); // Move the <stringelement> element to this position, displacing // the <someelement> downward. Remove the <someelement> XML, // effectively replacing <someelement> with <stringlist>. selectionCursor.moveXml(editCursor); editCursor.removeXml(); editCursor.dispose(); return rootDoc.validate(); }
The XmlObject.selectChildren
method you can retrieve an array of the child elements of a specified name. The method is overloaded to take java.xml.namespace.QName
instances or strings as parameters. The following code (based on the instance used in the preceding example) simply finds the <anyfoo>
element, an xs:any
, and replaces it with an <anybar>
element.
public boolean editExistingDocWithSelectChildren(RootDocument rootDoc) { String namespaceUri = "http://xmlbeans.apache.org/samples/any"; RootDocument.Root root = rootDoc.getRoot(); // Select the <anyfoo> children of <root>. XmlObject[] stringElements = root.selectChildren(new QName(m_namespaceUri, "anyfoo")); // If the element is there, replace it with another element. if (stringElements.length > 0) { XmlCursor editCursor = stringElements[0].newCursor(); editCursor.removeXml(); editCursor.beginElement(new QName(namespaceUri, "anybar")); editCursor.insertChars("some other text"); editCursor.dispose(); } return rootDoc.validate(); }
Through the getDomNode
method (exposed by XmlObject
and types generated from schema), you can get a live DOM node representing your XML. For example, calling myElement.getDomNode()
will return a org.w3c.dom.Node
instance representing the XML bound to myElement
. If you're already familiar with DOM-style access to XML, this can be a familiar alternative for handling xs:any
instances.
Using the instance introduced earlier in this topic, the following example adds a new <bar>
element between the first and second children of the <arrayofany>
element. The code also ensures that the first and second children are <stringelement>
and <someelement>
, respectively.
public boolean editExistingDocWithDOM(RootDocument rootDoc) { RootDocument.Root root = rootDoc.getRoot(); // Get the DOM nodes for the <arrayofany> element's children. Node arrayOfAnyNode = root.getArrayofany().getDomNode(); // You don't have get* accessors for any of the <arrayofany> // element's children, so use DOM to identify the first // and second elements while looping through the child list. NodeList childList = arrayOfAnyNode.getChildNodes(); Element firstElementChild = null; Element secondElementChild = null; // Find the first child element and make sure it's // <stringelement>. for (int i = 0; i < childList.getLength(); i++) { Node node = childList.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { if (node.getLocalName().equals("stringelement")) { firstElementChild = (Element)node; break; } } } if (firstElementChild == null) {return false;} // Find the second child element and make sure it's // <someelement>. Node node = firstElementChild.getNextSibling(); do { if (node.getNodeType() == Node.ELEMENT_NODE) { if (node.getLocalName().equals("someelement")) { secondElementChild = (Element)node; break; } } node = node.getNextSibling(); } while (node != null); if (secondElementChild == null) {return false;} // Create and insert a new <bar> element. Element fooElement = secondElementChild.getOwnerDocument().createElementNS("http://openuri.org","bar"); Node valueNode = fooElement.getOwnerDocument().createTextNode("some text"); fooElement.appendChild(valueNode); arrayOfAnyNode.insertBefore(fooElement, secondElementChild); return rootDoc.validate(); }
When you compile schema, the API generated from your schema is integrated with the XMLBeans type system that represents the underlying XML schema. All together, these types make up the schema type system to which your code has access. When handling XML based on the schema, you typically call methods of the API generated when you compiled the schema. However, for the cases when you want to get information about the schema itself, you use the schema type system API.
In the XMLBeans API, you have access to the system itself through SchemaTypeSystem and related classes. These make up a kind of "meta-API," or a view on the schema. You can use the schema type system API to discover the type system at run time. See the reference topic on that interface for an overview of the schema type system.
A schema is made up of schema components. Schema components are the pieces of a schema, such as a type definition, an element declaration, attribute declaration, and so on. To mirror these in the schema type system, a SchemaComponent instance represents a component in the underlying schema; separate components have corresponding types. For example you would have a SchemaType object for a CustomerType your schema defined, or a SchemaGlobalElement object for a global PurchaseOrder element. You would also have a SchemaType for built-in schema types, such as xs:string or xs:datetime. XMLBean provides a "signature" to describe each type. You can retrieve this signature by calling the SchemaType class's toString method.
The toString method returns XMLBeans' version of a unique signature for a schema type. This string is useful for debugging because it describes a given type even when the type doesn't have a name.
Note: It's important to remember that this signature is an XMLBeans convention, rather than a standard from the schema working group. The working group has not yet standardized a signature for XML schema types. As a result the signature you'll see from XMLBeans is subject to change — whatever the schema working group comes up with in the end (if anything) is probably what will be used by this API. In other words, don't write a program to decode the signature.
You can use the following description to understand how a signature is constructed.
T=<localname>@<targetNamespace>
The "T" is for "type," of course. "localname" is a convention used by qnames (qualified names), which include a local name and the namespace URI (if any). So an example might be:
T=customer@openuri.org
D=<document-element-name>@<targetNamespace> R=<attribute-type-name>@<targetNamespace>
The following rules are used for building a signature for an anonymous type.
If the element is form="qualified" (the usual default):
E=<eltname>|<signature of the type within which the elt is defined>If the element is form="unqualified":U=<eltname>|<signature of the type within which the elt is defined>If the attribute is form="unqualified" (the usual default):A=<attrname>|<signature of the type within the attr is defined>if the attribute is form="qualified":Q=<attrname>|<signature of the type within the attr is defined>
M=#|<signature of the containing union type>(The # is a number indicating which union member it is, by source order — such as 0,1,2, etc.)
B=|<signature of the containing base type for a restriction>I=|<signature of the containing list type>
So, for example, if you have a type that describes the list items within an attribute of an instance that looks like this:
<root mylist="432 999 143 123"/>
<schema targetNamespace="myNamespace" elementFormDefault="qualified"> <element name="root"> <complexType> <attribute name="mylist"> <simpleType> <list> <simpleType> <!--This is the type that the signature is for --> <restriction base="xs:nonNegativeInteger"> <totalDigits value="3"/>..
I=|A=mylist|E=root|D=root@myNamespace
You could read this as:
"The type of the list item | within the type of the mylist attribute's type | within the type of the root element | within the document type for <root> documents | in the myNamespace namespace".
Note that the signature structure mirrors the Java class structure generated by XMLBeans when compiling the schema. In other words, if you were to compile a schema that included the preceding snippet, you would be able to access an instance of the schema with Java code like the following:
SchemaType sType = RootDocument.Root.MyList.Item.type;
When you compile XML schema, the resulting API is made up of two categories of types: built-in types that mirror those in the schema specification and others that are generated from user-derived schema types. This topic provides an overview of the Java types generated for user-derived types, describing the methods the Java types provide. For more information about built-in types, see XMLBeans Support for Built-In Schema Types. For specific information about the methods exposed by generated types, see Methods for Generated Java Types.
In general, an API generated from schema is an intuitive means to access XML instances based on the schema. You'll probably find that for most uses it's unnecessary to know the rules for generating it in order to use it. However, for those cases when it's unclear what's going on behind the scenes (or if you're just curious), this topic describes the rules.
Note: The XMLBeans API also provides a way for you to get information about the type system itself — in other words, about the API and the underlying schema. For more information, see Introduction to Schema Type Signatures.
Each of the types generated when you compile a schema is designed specifically for access to XML instances conforming to that part of the schema. Start by taking a look at a simple XML and schema example. The following schema describes an XML document to contain a stock price quote.
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="price-quote"> <xs:complexType> <xs:sequence> <xs:element name="stock-symbol" type="xs:string"/> <xs:element name="stock-price" type="xs:float"/> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>
The following is an example of XML that conforms to this schema.
<price-quote> <stock-symbol>BEAS</stock-symbol> <stock-price>59.21</stock-price> </price-quote>
When you compile this schema, you get two generated XMLBeans interfaces: PriceQuoteDocument and PriceQuoteDocument.PriceQuote.
From the schema point of view, the generated PriceQuote interface represents the complex type you see inside the schema's price-quote element declaration. Looking at the XML instance, you can see that this complex type translates into a sequence of two elements, stock-symbol and stock-price. So it's not surprising that the PriceQuote interface exposes methods such as getStockPrice and setStockPrice to set the value stock-price element.
The PriceQuoteDocument interface, on the other hand, represents the price-quote document that contains the root price-quote element. XMLBeans creates a special "document" type for global element types. A document type provides a way for you to get and set the value of the underlying type, here represented by PriceQuote. The price-quote element is considered a global element because it can be referenced from anywhere else in the schema. For global elements, the XMLBeans schema compiler generates an interface whose name ends with "Document." This is because an XML schema has no way of defining a "root" element; any global element can be the root.
The following bit of Java code illustrates how you might use these interfaces to get the stock price contained in the XML.
public static float getStockPrice(java.io.File orderXML) throws Exception { PriceQuoteDocument docXML = PriceQuoteDocument.Factory.parse(orderXML); PriceQuote quoteXML = docXML.getPriceQuote(); float stockPrice = quoteXML.getStockPrice(); return stockPrice; }
This code loads the XML from a File object, converting the parse method's return value to a PriceQuoteDocument instance. It then uses this instance to get an instance of PriceQuote. With PriceQuote, the code extracts the stock price.
The XML schema specification provides a rich set of rules through which you can derive new types. When you generate interfaces from your schema, XMLBeans uses the schema's rules to determine how to generate interfaces. The following describes some of the guidelines by which this is done.
Interfaces are generated for schema types (both simple and complex). Anonymous schema types result in inner interfaces inside the type interface in which they are defined. Their name comes from the element or attribute in which they is defined.
Names for schema types become Java-friendly names when the schema is compiled. In other words, names such as "price-quote" become "PriceQuote." In addition, a schema's XML namespace URIs become package names for XMLBean types generated from the schema. The way this name translation is done is described by section C of the Java API for XML Binding (JAXB) specification at http://java.sun.com/xml/jaxb.html.
Here are a few examples:
Schema Target Namespace | XML Localname | Fully-Qualified XMLBean Type Name |
http://www.mycompany.com/2002/buyer | purchase-order-4 | com.mycompany.x2002.buyer.PurchaseOrder4 |
http://myco.com/sample.html | SampleDocument | com.myco.sample.SampleDocument |
http://openuri.org/test_case_1 | test_type | org.openuri.testCase1.TestType |
When there are name collisions, the generated types will have names with numerals appended — for example, "TestType2".
In schema, global element and attribute definitions are those that are declared at the top level of the schema (that is, immediately within the schema root element). Because they are global, they may be referenced from inside the schema by name. The creditReport (not the creditReportType complex type) element defined in the following schema is an example.
<xs:schema targetNamespace="http://openuri.org/samples/creditReport" xmlns:cr="http://openuri.org/samples/creditReport" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified"> <xs:complexType name="creditReportType"> <xs:sequence> <xs:element name="bankReport" type="xs:string"/> <xs:element name="taxReport" type="xs:string"/> </xs:sequence> </xs:complexType> <xs:element name="creditReport" type="cr:creditReportType"/> </xs:schema>
XMLBeans generates a separate interface for each of these. Also, global element and attribute types are somewhat unique in that the schema compiler will create special types to hold the globally defined element or attribute. The names of these types will be appended with "Document" (for elements) or "Attribute" (for attributes). You can retrieve the element or attribute itself (or create a new one) by calling the accessor methods that the special types provide. The following example would create a new instance of the creditReport element.
// Create an instance of the special document type. CreditReportDocument reportDoc = CreditReportDocument.Factory.newInstance(); /* * Use the document type to add a new creditReport element to the XML instance. * Note that the type returned by the addNewCreditReport method is the * creditReportType complex type defined for it in schema. */ CreditReportType report = reportDoc.addNewCreditReport();
A user-derived type is one defined with a complexType or simpleType element in schema. User-derived types at the top level of a schema are global. XMLBeans generates an interface for each of these, as it does with global elements and attributes. These interfaces include methods through which you can get and set the type's values, including any nested derived types it may contain. The following schema snippet defines a user-derived complex type called itemType, along with a priceType that uses it as the type for an item child element.
<xs:complexType name="itemType"> <xs:sequence> <xs:element name="name" type="xs:string"/> <xs:element name="amount" type="xs:int"/> <xs:element name="price" type="xs:double"/> </xs:sequence> </xs:complexType> <xs:complexType name="priceType"> <xs:sequence> <xs:element name="item" type="ps:itemType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:element name="price" type="ps:priceType"/>
By default, the generated Java type for itemType would be an interface called ItemType. With this type, you would be able to get and set the values of its name, amount, and price child elements. However, a user-derived type (as opposed to an element or attribute) is always intended for use as the type to which an element or attribute is bound. In other words, it's contained by an element or attribute. While you can create a new instance of a user-derived type, the new instance's underlying XML is a fragment. As the generated API would make clear, the itemType becomes the return type of a get method, or the parameter of a set method.
// Create a new price document. PriceDocument priceDoc = PriceDocument.Factory.newInstance(); PriceType price = priceDoc.getPrice(); /* * Create a new instance of ItemType and set the values of its * child elements. */ ItemType item = ItemType.Factory.newInstance(); item.setName("bicycle"); item.setAmount(12); item.setPrice(560.00); /* * Use the new ItemType instance to set the value of the * price element's first item child element. Notice that the set method * here is an "Array" method. This is because the item element * is defined with a maxOccurs="unbounded" attribute. It can occur * many times as a child of price. */ price.setItemArray(0, item);
When your schema includes named types that are declared locally—within the declaration of another element or type—the schema type's generated Java interface will be an inner interface within the type it's nested in.
For example, the following schema snippet defines name and gender elements nested within a person complex type. In particular, note that the gender element is defined as deriving from the xs:NMTOKEN built-in type.
<xs:complexType name="person"> <xs:sequence> <xs:element name="name" type="xs:string"/> <xs:element name="gender"> <xs:simpleType> <xs:restriction base="xs:NMTOKEN"> <xs:enumeration value="male"/> <xs:enumeration value="female"/> </xs:restriction> </xs:simpleType> </xs:element> </xs:sequence> </xs:complexType>
The generated interfaces for person and gender would be organized in source something like the following. Of course, you wouldn't see the source, but you can see here that the Gender interface is nested with Person. Also, notice that it extends XmlNMTOKEN, mirroring the schema.
public interface Person extends XmlObject { public interface Gender extends XmlNMTOKEN { // Methods omitted for this example } // Methods omitted for this example }
You could create a new instance of the Gender type in this way (there are also various alternatives to this):
// Create a new Person instance. Person person = Person.Factory.newInstance(); /* * Set the gender element's value using the * enumeration generated from the schema. */ person.setGender(Gender.FEMALE);
In addition to the 46 built-in simple types in XML schema, a schema can include its own custom simple types using xs:simpleType declarations. These user-derived simple types are always based on the built-in XML schema types. The built-in types can be modified by restricting them, taking unions of them, or making space-separated lists of them. Each XML simple type is translated into a Java type that provides access to the underlying data.
In schema, you can use xs:union to specify a simple type that is allowed to contain values of a number of other simple types. XMLBeans generates a type for a union, just as it generates a type for any other schema type. At run time, you can discover the underlying type of an instance of a union type by calling the XmlObject interface's instanceType method. Once you have determined the type, you can cast an instance of a union type to the actual underlying instance type.
<xs:simpleType name="intOrString"> <xs:union memberTypes="xs:int xs:string"> </xs:simpleType>
Given the preceding schema snippet, you could set the intOrString value to, say, 6 or "six". The union of xs:int and xs:string makes both allowable.
// Create a new instance of the type. IntOrString intOrString = IntOrString.Factory.newInstance(); intOrString.set("5"); // This code prints "XmlInt" to the console. System.out.println(intOrString.instanceType().getShortJavaName());
XML schema restrictions on simple XMLBeans types are enforced. So, for example, it is illegal to set a number outside its restricted range.
In schema, you can restrict numeric types to allow, for example, only a particular range of values. For such a restriction, XMLBeans tailors the resulting natural Java alternative. For example, suppose you have the following element defined in schema:
<xs:element name="number"> <xs:simpleType> <xs:restriction base="xs:integer"> <xs:minInclusive value="1"/> <xs:maxInclusive value="1000000"/> </xs:restriction> </xs:simpleType> </xs:element>
The type is restricted from xs:integer, but because the number's range is limited to between 1 and 1000000, it will fit into a Java int. A long or java.math.BigInteger would be too big for the need. In other words, the getNumber method generated for this type will return an int, rather than a BigInteger or a long.
By the same token, an long can be compiled to an int if the totalDigits attribute is <=9, or the min and max attribute values are within 32-bit 2s complement range.
The single primitive XML type xs:decimal can be restricted in several ways that influence the resulting natural Java type. For example, it can be:
In schema, you can derive a new type by restricting a built-in type so that only a finite set of values are allowable. Where schema does this by restricting xs:string, XMLBeans generates a special Enum type. With an Enum, you can select the enumerated value either by its String value or by a numeric index. The index's value is determined based on the String value's order in the schema. Having an index can be useful in Java switch statements.
For example, suppose you had a document containing price elements whose type was the priceType defined in the following schema snippet:
<xs:complexType name="priceType"> <xs:sequence> <xs:element name="item" type="ps:itemType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:attribute name="threshold"> <xs:simpleType> <xs:restriction base="xs:string"> <xs:enumeration value="Below10Dollars"/> <xs:enumeration value="Between10And20Dollars"/> <xs:enumeration value="Above20Dollars"/> </xs:restriction> </xs:simpleType> </xs:attribute> </xs:complexType>
Using types generated from the schema, you would be able to write the following Java code to "switch" on the threshold attribute's enumeration:
/* * Use the intValue method provided by the Enum type to determine the threshold * attribute's current enumeration value. */ switch(priceElements[i].getThreshold().intValue()) { // Use the Threshold type's enumeration values to test for an attribute value. case PriceType.Threshold.INT_BELOW_10_DOLLARS: zeroBuffer.append(item.getTitle() + "\n"); break; case PriceType.Threshold.INT_BETWEEN_10_AND_20_DOLLARS: tenBuffer.append(item.getTitle() + "\n"); break; case PriceType.Threshold.INT_ABOVE_20_DOLLARS: twentyBuffer.append(item.getTitle() + "\n"); break; default: System.out.println("Yo! Something unexpected happened!"); break; }
Methods for Types Generated From Schema
As you may have seen in Getting Started with XMLBeans, you use the types generated from schema to access XML instances based on the schema. If you're familiar with the JavaBeans technology, the conventions used in the generated API will be recognizable.
In general, elements and attributes are treated as "properties" in the JavaBeans sense. In other words, as you would with JavaBeans properties, you manipulate parts of the XML through accessor methods such as getCustomer() (where you have a "customer" element), setId(String) (where you have an "id" attribute), and so on. However, because schema structures can be somewhat complex, XMLBeans provides several other method styles for handling those structures in XML instances.
Several methods are generated for each element or attribute within the complex type. This topic lists each method that could be generated for a given element or attribute.
Note that whether or not a given method is generated is based on how the element or attribute is defined in schema. For example, a customer element definition with a maxOccurs attribute value of 1 will result in a getCustomer method, but not a getCustomerArray method — after all, only one customer element is possible in an instance document.
Note, too, that there may be two sets of parallel methods: one whose prototype starts with an "x". An "x" method such as xgetName or xsetName would be generated for elements or attribute whose type is a simple type. A simple type may be one of the 44 built-in simple types or may be a restriction in schema of one of those built-in types. Of course, an attribute will always be of a simple type. For built-in simple types, an "x" method will get or set one of the types provided with XMLBeans, such as XmlString, XmlInteger, XmlGDay, and so on. For derived types, the "x" method will get or set a generated type.
Methods generated for elements or attributes that allow a single occurrence. An element is singular if it was declared with maxOccurs="1". An attribute is singular if it was not declared with use="prohibited".
Type getFoo() void setFoo(Type newValue)
Returns or sets the value of Foo. Generated when Foo is an attribute, or is an element that can occur only once as a child.
XmlType xgetFoo() void xsetFoo(XmlType newValue)
Returns or sets the value of Foo as an XMLBean simple type. These methods are generated if Foo's type is defined in schema as a simpleType.
boolean isNilFoo() void setNilFoo()
Determines or specifies whether the Foo element is nil (in other words, "null" in schema terms), meaning it can be empty. A nil element looks something like this:<foo/>These methods are only generated when an element type is declared as nillable in schema — it has a nillable="true" attribute.
XmlType addNewFoo()
Adds a new Foo as an XMLBean simple to the document, or returns Foo's value if one exists already.
boolean isSetFoo() void unSetFoo()
Determines whether the Foo element or attribute exists in the document; removes Foo. These methods are generated for elements and attributes that are optional. In schema, and optional element has an minOccurs attribute set to "0"; an optional attribute has a use attribute set to "optional".
Methods generated for elements that allow multiple occurrences.
An element may occur multiple times if it has a maxOccurs attribute set to "unbounded" or greater than 1. Attributes can't occur multiple times.
Type[] getFooArray() void setFooArray(Type[] newValue)
Returns or sets all of the Foo elements.// Get an array of the all of the purchase-order elements item children. Item[] items = myPO.getItemArray();
Type getFooArray(int index) void setFooArray(Type newValue, int index)
Returns or sets the Foo child element at the specified index.// Sets the value of the third item child element. myPO.setItem(newItem, 2);
int sizeOfFooArray()
Returns the number of Foo child elements.// Returns the number of item child elements. int itemCount = myPO.sizeOfItemArray();
void removeFoo(int index)
Removes the Foo child element at the specified index.
XmlType[] xgetFooArray() void xsetFooArray(XmlType[] arrayOfNewValues)
Returns or sets all of the Foo elements as XMLBeans simple types. Generated only when the Foo element is defined as a simple type./* * Returns values of all the phone child elements of an employee element, * where the phone element has been defined as xs:string. */ XmlString[] empPhones = currentEmployee.xGetPhoneArray();
XmlType xgetFooArray(int index) void xsetFooArray(int index, XmlType newValue)
Returns or sets the Foo element at the specified index, using an XMLBeans simple type value. Generated for an element defined as a simple type in schema.
void insertFoo(int index, FooType newValue)
Inserts the specified Foo child element at the specified index.
void addFoo(FooType newValue)
Adds the specified Foo to the end of the list of Foo child elements.
XmlType insertNewFoo(int index)
Inserts a new Foo at the specified index, returning an XMLBeans simple type representing the new element; returns the existing Foo if there's already one at index.
XmlType addNewFoo()
Adds a new Foo element to the end of the list of Foo child elements, returning an XMLBeans simple type representing the newly added element.
boolean isNilFooArray(int index) void setNilFooArray(int index)
Determines or specifies whether the Foo element at the specified index is nil.
XML cursors are a way to navigate through an XML instance document. Once you load an XML document, you can create a cursor to represent a specific place in the XML. Because you can use a cursor with or without a schema corresponding to the XML, cursors are an ideal way to handle XML without a schema.
With an XML cursor, you can:
When you're finished using a cursor, your code should call its dispose method.
With an XML instance document bound to XmlObject (or a type inheriting from it), you create a new cursor by calling the newCursor method. The XmlCursor interface represents a cursor. From a cursor standpoint, an XML document is a collection of tokens that represent the kinds of things that can appear in XML. These include attributes, the start and end of elements, comments, and so on. Each piece of information in XML is represented by a token type.
Note: For a more complete description of XML tokens, see Understanding XML Tokens.
For example, the following code loads the XML instance described above from a File object, then creates a new cursor. The toFirstChild takes the cursor to the start tag of the batchWidgetOrder document element. The code then prints the type for the token at the cursor's location, along with the XML the cursor represents—in other words, Token type: START / and the batchWidgetOrderElement and its contents.
public static void insertCursor(File orderFile) throws Exception { BatchWidgetOrderDocument xmlDoc = BatchWidgetOrderDocument.Factory.parse(orderFile); XmlCursor orderCursor = xmlDoc.newCursor(); orderCursor.toFirstChild(); System.out.println("Token type: " + orderCursor.currentTokenType() + " / " + orderCursor.xmlText()); }
Note: The XmlCursor interface provides many methods you can use to put a cursor where you want it. For a list of those methods, see XmlCursor Interface.
The XmlCursor interface provides several methods you can use to add elements and attributes to XML.
One way to add new XML is with the beginElement method. This method is designed to insert a new element at the cursor's location, and do it so the cursor ends up between the new element's START and END tokens. From this position, you can insert attributes (they're automatically placed in the start tag, where they belong) and insert a value. Here's an example:
// Create a new chunk of XML. XmlObject newXml = XmlObject.Factory.newInstance(); /* * Insert a new cursor and move it to the first START token (where the * XML actually begins. */ XmlCursor cursor = newXml.newCursor(); cursor.toNextToken(); // Begin a new item element whose namespace URI is "http://openuri.org". cursor.beginElement("item", "http://openuri.org/"); // Insert an ID attribute on the item element, along with an attribute value. cursor.insertAttributeWithValue("id", "4056404"); // Insert "bicycle" as an element value. cursor.insertChars("bicycle"); cursor.dispose();
This example results in something like the following:
<ns1:item id="4056404" xmlns:ns1="http://openuri.org/">bicycle</ns1:item>
When you want to move a cursor around, but want to keep track of a former location, you can use the XmlCursor interface's push and pop methods. The push method pushes the cursor's current location onto a stack of locations maintained for that particular cursor; the pop method removes the location from the top of the stack and moves the cursor to that location.
For example, consider the following <employee> element, used in the example below.
<employee> <name>Gladys Kravitz</name> <address location="home"> <street>1313 Mockingbird Lane</street> <city>Seattle</city> <state>WA</state> <zip>98115</zip> </address> <address location="work"> <street>2011 152nd Avenue NE</street> <city>Redmond</city> <state>WA</state> <zip>98052</zip> </address> <phone location="work">(425) 555-6897</phone> <phone location="home">(206) 555-6594</phone> <phone location="mobile">(206) 555-7894</phone> </employee>
The following Java code illustrates how you can use push and pop to put the cursor back to a saved location after a bit of traveling.
/** * Pass to the trySelectPath method an XmlObject instance that contains * the XML above. */ public void trySelectPath(XmlObject xml) { /* * Inserts the cursor at the STARTDOC token (the very beginning, * before any elements). */ XmlCursor cursor = xml.newCursor(); // Moves the cursor to just before <employee> cursor.toFirstChild(); // Pushes the cursor's current location onto the stack. cursor.push(); // Moves the cursor to just before the "work" <phone> element. cursor.toChild(2); // Moves the cursor to just before the "home" <phone> element. cursor.toNextSibling(); // Moves the cursor back to just before <employee> cursor.pop(); }
Of course, you can call push and pop multiple times. Each new call to the push method pushes the current location onto the stack. As you call the pop method, you're always getting what's on top of the stack. So if you called push three times before calling pop — 1, 2, 3 — calling pop three times would get those locations in reverse order — 3, 2, 1.
The push and pop methods can be handy as an alternative to creating new cursors that are designed simply to mark a particular location while you move another cursor around. The resources required to maintain a location stack through push and pop are far less than those needed by cursors.
When you're through with a cursor, your code should call its dispose method to indicate that it's no longer needed.
You can use XPath and XQuery to retrieve specific pieces of XML as you might retrieve data from a database. XQuery and XPath provide a syntax for specifying which elements and attributes you're interested in. The XMLBeans API provides two methods for executing XQuery and XPath expressions, and two ways to use them. The methods are selectPath for XPath and execQuery for XQuery.
You can call them from and XmlObject instance (or a generated type inheriting from it) or an XmlCursor instance. As noted below, each of the four methods works slightly differently; be sure to keep these differences in mind when choosing your approach.
Note: Both XQuery and complex XPath expressions require additional classes on the class path, as noted in the sections that follow. Also, be sure to see the XMLBeans installation instructions.
You can execute XPath expressions use the selectPath method. When you use XPath with the selectPath method, the value returned is view of values from the current document — not a copy of those values. In other words, changes your code makes to XML returned by the selectPath method change the XML in the document queried against. In contrast, with XQuery executed using the execQuery method, the value returned is a copy of values in the XML queried against.
Note that XPath itself does not provide syntax for declaring prefix to URI bindings. For user convenience, we allow XQuery syntax to be used for such purposes. You can consult the latest XQuery draft when using syntax for declaring namespaces.
Note: By default, XMLBeans supports only very simple XPath expressions. To execute complex expressions — such as those with predicates, function calls, and the like — you will need xbean_xpath.jar and the Saxon jars (see below) on your class path. xbean_xpath.jar is among those created when you build XMLBeans from source. You may need to download the Saxon jars yourself.
When called from XmlObject (or a type that
inherits from it), the selectPath
method returns an array of objects. If the expression
is executed against types generated from schema, then the type for the returned
array is one of the Java types corresponding to the schema, and you can cast it accordingly.
For example, imagine you have the following XML containing employee information. You've compiled the schema describing this XML and the types generated from schema are available to your code.
<xq:employees xmlns:xq="http://xmlbeans.apache.org/samples/xquery/employees"> <xq:employee> <xq:name>Fred Jones</xq:name> <xq:address location="home"> <xq:street>900 Aurora Ave.</xq:street> <xq:city>Seattle</xq:city> <xq:state>WA</xq:state> <xq:zip>98115</xq:zip> </xq:address> <xq:address location="work"> <xq:street>2011 152nd Avenue NE</xq:street> <xq:city>Redmond</xq:city> <xq:state>WA</xq:state> <xq:zip>98052</xq:zip> </xq:address> <xq:phone location="work">(425)555-5665</xq:phone> <xq:phone location="home">(206)555-5555</xq:phone> <xq:phone location="mobile">(206)555-4321</xq:phone> </xq:employee> </xq:employees>If you wanted to find the phone numbers whose area code was 206, you could capture the XPath expression in this way:
String queryExpression = "declare namespace xq='http://xmlbeans.apache.org/samples/xquery/employees';" + "$this/xq:employees/xq:employee/xq:phone[contains(., '(206)')]";
Notice in the query expression that the variable $this represents the current context node (the XmlObject that you are querying from). In this example you are querying from the document level XmlObject.
You could then print the results with code such as the following:
// Retrieve the matching phone elements and assign the results to the corresponding // generated type. PhoneType[] phones = (PhoneType[])empDoc.selectPath(queryExpression); // Loop through the results, printing the value of the phone element. for (int i = 0; i < phones.length; i++) { System.out.println(phones[i].stringValue()); }
When called from an XmlCursor instance, the selectPath method retrieves a list of selections, or locations in the XML. The selections are remembered by the cursor instance. You can use methods such as toNextSelection to navigate among them.
The selectPath method takes an XPath expression. If the expression returns any results, each of those results is added as a selection to the cursor's list of selections. You can move through these selections in the way you might use java.util.Iterator methods to move through a collection.
For example, for a path such as $this/employees/employee,
the cursor instance from which you called selectPath
would include a selection for each employee element found by
the expression. Note that the variable $this
is always bound to the current context node, which in this example is the
document. After calling the selectPath method,
you would use various "selection"-related methods to work with
the results. These methods include:
The following example shows how you might use selectPath, in combination with the push and pop methods, to maneuver through XML, retrieving specific values.
public void printZipsAndWorkPhones(XmlObject xml) { // Declare the namespace that will be used. String xqNamespace = "declare namespace xq='http://xmlbeans.apache.org/samples/xquery/employees';"; // Insert a cursor and move it to the first element. XmlCursor cursor = xml.newCursor(); cursor.toFirstChild(); // Save the cursor's current location by pushing it // onto a stack of saved locations. cursor.push(); // Query for zip elements. cursor.selectPath(xqNamespace + "$this//xq:zip"); // Loop through the list of selections, getting the value of // each element. while (cursor.toNextSelection()) { System.out.println(cursor.getTextValue()); } // Pop the saved location off the stack. cursor.pop(); // Query again from the top, this time for work phone numbers. cursor.selectPath(xqNamespace + "$this//xq:phone[@location='work']"); // Move the cursor to the first selection, then print that element's // value. cursor.toNextSelection(); System.out.println(cursor.getTextValue()); // Dispose of the cursor. cursor.dispose(); }
Using selections is somewhat like tracking the locations of multiple cursors with a single cursor. This becomes especially clear when you remove the XML associated with a selection. When you do so the selection itself remains at the location where the removed XML was, but now the selection's location is immediately before the XML that was after the XML you removed. In other words, removing XML created a kind of vacuum that was filled by the XML after it, which shifted up into the space — up into position immediately after the selection location. This is exactly the same as if the selection had been another cursor.
Finally, when using selections keep in mind that the list of selections is in a sense "live". The cursor you're working with is keeping track of the selections in the list. In other words, be sure to call the clearSelections method when you're finished with the selections, just as you should call the XmlCursor.dispose() method when you're finished using the cursor.
You use the execQuery method to execute XQuery
expressions. With XQuery expressions, XML returned is a copy of XML in the document queried against. In other words, changes your code makes to the values returned by execQuery
are not reflected in the document queried against.
Note: To execute XQuery expressions, you must have the SaxonB 8.6.1 versions of the saxon8.jar and saxon8-dom.jar files on your classpath. These are two of the jars from inside the zip file saxonb8-6-1.zip which can be downloaded from the Saxon web site. If you build XMLBeans from source then the saxonb8-6-1.zip file and the two Saxon jar files are available in the external/lib directory.
As with selectPath, calling execQuery from an XmlObject instance will return an XmlObject array.
The following example retrieves work <zip>
elements from the incoming XML, adding the elements as children to a new <zip-list>
element.
public boolean collectZips(XmlObject empDoc) { String namespaceDeclaration = "declare namespace xq='http://xmlbeans.apache.org/samples/xquery/employees';"; // The query is designed to return results, so return // true if it does. boolean hasResults = false; // The expression: Get the <zip> elements and return them as children // of a new <zip-list> element. String queryExpression = "let $e := $this/xq:employees " + "return " + "<zip-list> " + "{for $z in $e/xq:employee/xq:address/xq:zip " + "return $z} " + "</zip-list>"; // Execute the query. Results will be copies of the XML queried against, // stored as members of an XmlObject array. XmlObject[] results = empDoc.execQuery(namespaceDeclaration + queryExpression); // Print the results. if (results.length > 0) { hasResults = true; System.out.println("The query results: \n"); System.out.println(results[0].toString() + "\n"); } return hasResults; }
Unlike the selectPath
method called from a cursor, the execQuery method doesn't return void
. Instead it returns an XmlCursor instance positioned at the beginning of a new XML document representing
the query results. Rather than accessing results as selections, you use the cursor to move through the results in typical cursor fashion (for more information, see Navigating
XML with Cursors). The models are very different.
As always, you can cast the results to a type generated from schema if you know that the results conform to that type.
The following example retrieves work <phone>
elements from the incoming XML, then changes the number in the results.
public boolean updateWorkPhone(XmlObject empDoc) { boolean hasResults = false; // A cursor instance to query with. XmlCursor empCursor = empDoc.newCursor(); empCursor.toNextToken(); // The expression: Get theelements with elements whose // value is "WA". String queryExpression = "for $e in $this/xq:employees/xq:employee " + "let $s := $e/xq:address/xq:state " + "where $s = 'WA' " + "return $e//xq:phone[@location='work']"; // Execute the query. Results, if any, will be available at // the position of the resultCursor in a new XML document. XmlCursor resultCursor = empCursor.execQuery(namespaceDeclaration + queryExpression); System.out.println("The query results, element copies made " + "from the received document: \n"); System.out.println(resultCursor.getObject().toString() + "\n"); // If there are results, the results will be children of the fragment root // where the new cursor is positioned. This statement tests for children // and moves the cursor if to the first if it exists. if (resultCursor.toFirstChild()) { hasResults = true; // Use the cursor to loop through the results, printing each sibling // element returned by the query. int i = 0; do { // Change the phone numbers. XmlCursor editCursor = resultCursor.newCursor(); editCursor.toLastAttribute(); editCursor.toNextToken(); editCursor.removeXml(); editCursor.insertChars("(206)555-1234"); } while (resultCursor.toNextSibling()); resultCursor.toStartDoc(); System.out.println("The query results after changes: \n"); System.out.println(resultCursor.getObject().toString() + "\n"); System.out.println("The received document -- note that it is unchanged. " + "Changes were made to the copy created by the execQuery method. \n"); System.out.println(empDoc + "\n"); } return hasResults; }
Understanding XML Tokens
An XML cursor (an instance of the XmlCursor interface) moves from token to token as your code moves the cursor. When you move a cursor using a method such as toParent, toFirstAttribute, toPrevSibling, and so on, the cursor moves to the token fitting the description. If there is no appropriate token to move to, the cursor remains where it is, and false is returned to indicate that it didn't move. For example, if the cursor is at the ENDDOC token (the last tag in the document), a call to the toNextSibling method will not move the cursor and will return false to indicate that the move was unsuccessful.
Note that while you can call the XmlCursor.currentTokenType method to find out which token type the cursor is at, you might find it more convenient to use a method such as isEnddoc. The XmlCursor interface provides several methods that make it easy to discover whether the cursor you're moving is at the token you're looking for. These methods, such as isStart, isAttr, isText, and so on, return a boolean value that indicates whether the cursor is at the token type in question.
Tokens are represented by constants in the TokenType class, an inner class of the XmlCursor interface. Each has a constant you can use in switch statements to perform by-token actions. The following table lists the token types:
Token Type | Switch Constant | Description |
STARTDOC | INT_STARTDOC | Represents the start of the XML. Always the first token. The document element itself is represented by a START token, not the STARTDOC token. |
ENDDOC | INT_ENDDOC | Represents the end of the XML. Always the last token. |
START | INT_START | Represents the start of an element. |
END | INT_END | Represents the end of an element. The END token has no value, but marks the element's end. |
TEXT | INT_TEXT | Represents text. |
ATTR | INT_ATTR | Represents an attribute. ATTR tokens are allowed to appear after a STARTDOC or START token. |
NAMESPACE | INT_NAMESPACE | Represents a namespace (xmlns) attribute. Also only allowed after START or STARTDOC tokens. |
COMMENT | INT_COMMENT | Represents a comment. |
PROCINST | INT_PROCINST | Represents a processing instruction. |
As you use a cursor to navigate through XML, you can use one of the convenience methods described above to discover whether you're at the token you're looking for, or use the XmlCursor.currentTokenType method to discover the current token's type. The following figure illustrates example locations for token types:
Here's a bit of code illustrating how you might use a Java switch statement to test for the START token type.
// Take an incoming XmlObject and insert a cursor. XmlCursor documentCursor = xmlDoc.newCursor(); /* * Loop through the document, passing the cursor when it stops at each token * to a function designed to discover the token type. Continue the loop * as long at the cursor is at a token (until it reaches the end). */ while (!documentCursor.toNextToken().isNone()) { /* * Use the intValue method to return the int corresponding to the * current token type. If it is the value for INT_START, * then you have a match. */ switch (cursor.currentTokenType().intValue()) { case TokenType.INT_START: // Print out the token type and a message. System.out.println(cursor.currentTokenType() + "; cursor is at the start of an element."); break; } } // Be sure to dispose of a cursor when you're finished. documentCursor.dispose();
The scope of an XML cursor is the XML document in which it is created. For example, you can create a cursor at the orderItem element in the example earlier in this topic. If you then use that XmlCursor instance's toNextToken method to move the cursor until it won't move any further, you'll have reached the ENDDOC token. In this example, that's at the </batchWidgetOrder> tag. In other words, the cursor's scope is not limited to the element at which it was created.
Using Bookmarks to Annotate XML
You can use a cursor to insert bookmarks that annotate XML with markers containing information you design. These bookmarks aren't written into the XML itself, but in a sense "hang" from the location where it was inserted. In this way you can associate arbitrary pieces of information with specific parts of the XML.
You design your own bookmark classes by extending XmlBookmark, a nested class of XmlCursor. You can design your bookmark class to contain information specific to your needs.
In the following example, OrderBookmark is an inner class that extends XmlCursor.XmlBookmark. It merely stores a piece of text.
/* * The OrderBookmark class includes a constructor through which you will * insert your bookmark's content. It also includes get and set methods * you can use to retrieve and change the content. */ static class OrderBookmark extends XmlCursor.XmlBookmark { public OrderBookmark (String text) { TEXT = text; } public String TEXT; public String getText() { return TEXT; } public void setText(String newText) { TEXT = newText; } }
You can use instances of this class to store bookmarks at places in your XML. The following excerpt of code creates a cursor and an instance of the OrderBookmark class. Then it uses the cursor to insert the bookmark at the cursor's current location.
XmlCursor orderCursor = xmlDoc.newCursor(); OrderBookmark thisBookmark = new OrderBookmark("foo"); orderCursor.setBookmark(thisAnnotation);
An essential part of schema-related work is validating instances based on the schema. XMLBeans provides a number of ways for you to ensure your instances are valid, both at the command line and programmatically at run time.
XMLBeans' schema-oriented approach to handling XML makes validation an important part of its work. However, XMLBeans has a specific approach to validation that's helpful to keep in mind when you're working.
Validation features include the following:
validate
methods return true
or false
to indicate whether the instance is valid. You can also capture error information if you want to when validating programmatically. To do this, you specify an error listener.XmlOptions.setCompileNoValidation
method.)Given XMLBeans' focus on schema-oriented work, it's natural to assume that it might check up on you as your code is making changes to an instance — that it might prevent your code from doing something that would render the instance invalid along the way. But, by default, it doesn't. The design of XMLBeans assumes that an XML instance might go through multiple invalid states before changes are complete. As a result, generally speaking, XMLBeans keeps quiet while changes are occurring.
Note: The exception to this rule is that XMLBeans validates your schema when you're compiling it using scomp or the xmlbean Ant task.
But it's not hard to get the impression that it does. For example, imagine that you're parsing an XML instance using a statement such as the following:
MyXmlSchemaType myXmlBean = MyXmlSchemaType.Factory.parse(myXml);
If the namespace declared in the myXml instance doesn't match the target namespace of the schema from which MyXmlSchemaType was generated, parsing will fail with an error message. Likewise, you'll get messages for other mismatches between the shape of myXml and the XML shape described by the schema.
But these failures and messages don't result from validation. Instead, all XMLBeans is doing is a not-very-deep check to see if the instance shouldn't be bound to the XMLBeans type generated from schema. In other words, the checking done at the parsing stage is simply a "low bar" effort to avoid trouble down the road.
Validation, on the other hand, is designed to verify that the instance conforms completely to the schema.
So you can validate in any of three ways:
XMLBeans tools for validation include command-line tools and APIs.
Among the many command-line tools XMLBeans provides, you'll find two that are specifically for validation.
You'll find the validate
tool in the bin directory of your XMLBeans installation.
You'll find the svalidate
tool in the bin directory of your XMLBeans installation.
XMLBeans APIs provide ways for you to validate on request — say, after your code has finished editing an instance and before it passes the instance elsewhere. You can also specify that your calls to set* methods should validate on-the-fly the instance that is being edited; you do this as an option when your code creates the XMLBeans schema type instance.
Both the validate
methods described here are available from any XMLBeans type generated from schema during schema compilation (because all such types inherit from XmlObject
). Both methods are designed to validate the instance that is bound to the type from which the method is called. For example, if your schema defines a <purchase-order>
element with <item>
children, calling the myItem.validate()
method will validate the <item>
instance bound to Item
. This includes the <item>
element's children, but not the <purchase-order>
element or the <item>
element's siblings.
Both methods return a boolean
to indicate validity, and one of the methods lets you specify options for validation, such as capturing messages about why an invalid instance is invalid.
XmlObject.validate()
— Returns true
if the instance is valid.XmlObject.validate(XmlOptions)
— Returns true
if the instance is valid, using the specified XmlOptions
instance to customize validation.
In particular, you can use the XmlOptions.setErrorListener
method to specify a Collection
instance with which to capture messages pertaining to invalid instances. For an example, see the Javadoc for this method.
Through the XmlOptions
class, you can specify options to use during validation. The options include the following:
Also, see the section on validating as you go for information about using the XmlOptions.setValidateOnSet
method.
When you'll be validating with one of the validate
methods, you can specify a java.util.Collection
implementation as an error listener. As validation occurs, errors are added to the listener. After validation (and if the instance is found to be invalid) you can examine the errors. Here's an example:
// Set up the validation error listener. ArrayList validationErrors = new ArrayList(); XmlOptions validationOptions = new XmlOptions(); validationOptions.setErrorListener(validationErrors); MyDocument myDoc = MyDocument.Factory.parse(pathToXml); // Do some editing to myDoc. // During validation, errors are added to the ArrayList for // retrieval and printing by the printErrors method. boolean isValid = myDoc.validate(validationOptions); // Print the errors if the XML is invalid. if (!isValid) { Iterator iter = validationErrors.iterator(); while (iter.hasNext()) { System.out.println(">> " + iter.next() + "\n"); } }
By default, an XML instance will not be validated at run time as your code makes changes. However, you can change this behavior for limited on-the-fly validation. To do this, you specify the "validate on set" option when you create the XMLBeans type instance — you do this with the XmlOptions.setValidateOnSet
method.
When you specify this option, XMLBeans with throw an exception when your code invalidates the XML through a set* method. Note that you can't specify an error listener for use in conjunction with this means of validating. Also, with "validate on set," only simple schema types will be validated. Schema types not validated by this approach include, for example, those defining elements with attributes or elements with children.
Because its functionality is limited to simple schema types and it validates for set* method calls, you should regard this validation approach as a debugging tool, rather than an alternative to using a validate
method. For example, you might use it to determine which errant bit of code is creating an invalid chunk of XML.
Note: This sort of validation is not supported during changes you make using an XmlCursor
instance.
Among the methods you can use to create an XMLBeans instance — the parse
methods and the newInstance
method — you'll find versions that take an XmlOptions
instance as a parameter. Specifying this option would look something like the following:
XmlOptions validateOptions = new XmlOptions(); // Tell XMLBeans you want to validate on the fly. validateOptions.setValidateOnSet(); // Create the new instance, specifying the option. PurchaseOrder newPo = PurchaseOrder.Factory.newInstance(validateOptions); // ... Code to edit the instance via get and set methods ...xmlbeans-2.6.0/docs/guide/conXMLBeansSupportBuiltInSchemaTypes.html 100644 0 0 45565 11361341575 22602 0 ustar 0 0
Just as with types in XML schema, the XMLBeans types based on schema are arranged in a hierarchy. In general, the hierarchy of XMLBean types mirrors the hierarchy of the schema types themselves. XML schema types all inherit from xs:anyType (which is at the root of the hierarchy); XMLBeans types inherit from XmlObject.
In XML schema, xs:anyType is the root type for two type categories: built-in and user-derived. Built-in schema types are common types defined by the XML schema specification. User-derived types are those you define in your schema. This topic lists the built-in types provided with XMLBeans. For information about user-derived types and the Java types generated from them, see Java Types Generated from User-Derived Schema Types.
The following figure illustrates the hierarchy of types, showing both built-in schema types and their XMLBeans parallels. Notice, too, that nearly all of the built-in types are also available as natural Java types.
As you can see from the figure above, all 46 built-in schema types are represented by an XMLBean type provided with XMLBeans. When using built-in XMLBean types, keep in mind that:
The following table lists the built-in schema types, along with their XMLBeans and natural Java parallels. Unless otherwise noted, natural Java types are in the java.lang package; XMLBean types are in the org.apache.xmlbeans package.
XMLBeans includes several command-line tools you might find handy as shortcuts for common tasks. You'll find these tools in the bin directory of the XMLBeans installation or source tree.
Prints the contents of an XSB file in human-readable form. An XSB file contains schema meta information needed to perform tasks such as binding and validation. "XSB" stands for XML Schema Binary.
dumpxsb myfile.xsb
The following command and output example use an XSB file generated by compiling the schema (in EasyPo.xsd) that accompanies the SubstitutionGroup sample.
dumpxsb PurchaseOrderDocument.xsb
Output:
PurchaseOrderDocument.xsb Magic cookie: da7ababe Major version: 2 Minor version: 22 Release number: 0 Filetype: FILETYPE_SCHEMAPOINTER String pool (2): 1 = "schema.system.s633ECC92E6CC0ACA137B11B7B38CA3A8" Type system: schema.system.s633ECC92E6CC0ACA137B11B7B38CA3A8
Generates XML schema from XML instance files.
inst2xsd [options] instance.xml*
The following example generates schema0.xsd from Purchase-Order.xml, with salami slice schema design, simple content types detected where possible, and enumerations limited to elements with four different values.
inst2xsd -design ss -simple-content-types smart -enumerations 4 Purchase-Order.xml
Compiles schema into Java XMLBeans classes and metadata. Schema-related work with XMLBeans begins by compiling schema to generated Java types. You can use scomp to compile schema from the command line. XMLBeans also provides an Ant task, xmlbeans, which you can use to compile schemas. For run-time schema compilation that doesn't generate files, see the org.apache.xmlbeans.XmlBeans.compileXsd methods.
For more information about the types resulting from compiling schema, see Java Types Generated from User-Derived Schema Types, XMLBeans Support for Built-In Schema Types, and Methods for Types Generated From Schema.
For more information on getting started with XMLBeans, see Getting Started with XMLBeans.
scomp [options] [dirs]* [schemaFile.xsd]* [service.wsdl]* [config.xsdconfig]*
##local
to
specify the no-namespace in that list. org.apache.xml.resolver.tools.CatalogResolver
for
resolving. Note that to use this option, your classpath must include resolver.jar
from http://xml.apache.org/commons/components/resolver/index.html). Copy resolver.jar
to the XMLBEANS_HOME/lib directory, so that the script can pick it up from
there. You can use the sdownload tool to ensure that
required schemas are present for compilation. In the following example, scomp compiles EasyPO.xsd, guiding type naming with po.xsdconfig. scomp puts generated CLASS and XSB files into a classes directory one level up, and JAVA source files into a src directory one level up. Source files will be compatible with Java version 1.5.
scomp -d ..\classes -src ..\src -javasource 1.5 EasyPO.xsd po.xsdconfig
Here, scomp compiles all of the contents of the schemas directory and puts the generated files into poschema.jar one level up.
scomp -out ..\poschema.jar schemas
The following example generates JAVA source and XSB files from the schema in EasyPO.xsd. No CLASS files are generated, and the JAVA and XSB files are put into src and xsb directories, respectively.
scomp -srconly -src ..\src -d ..\xsb EasyPO.xsd
When the schema features imports or includes and you want to use a catalog,
you can tell scomp to use the default catalog resolver (org.apache.xml.resolver.tools.CatalogResolver
);
you specify a catalog file with the -catalog option, as in the example below.
(Note that this requires resolver.jar, as noted above for the -catalog option.)
In this example, scomp compiles schemaThatUsesRequiredSchema.xsd into myschemas.jar,
resolving imports from requiredSchema.xsd through xsdownload.xml. The sdownload
tool is executed first — this ensures that requiredSchema.xsd is present
for compilation, but does not actually download requiredSchema.xsd unless the
URL at which it's found isn't already cached. This is more efficient than using
scomp's -dl option, which attempts to download every time.
sdownload "http://some.org/requiredSchema.xsd" scomp -out ..\myschemas.jar -catalog xsdownload.xml schemaThatUsesRequiredSchema.xsd
When a schema features multiple element declarations of the same qname, such as multiple <xs:any> particles, you might want to disable to "unique particle validation" rule, which would ordinarily invalidate the schema. To do this, use the -noupa option, as in the following example.
scomp -out ..\myschemas.jar -noupa schemas
Copies the XML schema at the specified URL to the specified file.
schemacopy sourceurl [targetfile]
Maintains "xsdownload.xml," an index of locally downloaded XSD files. URLs that are specified are downloaded if they aren't already cached. If no files or URLs are specified, all indexed files are relevant.
You can use this tool when using scomp, in conjunction with scomp's -catalog option, to ensure the presence of schemas that are required for compilation because they're imported or included. This is an alternative to using scomp's -dl option, which would hit the Internet on every invocation of scomp. When you use sdownload with -catalog, the download occurs only if the URL is not already cached. See the scomp section for an example.
sdownload [-dir directory] [-refresh] [-recurse] [-sync] [url/file]
Factors redundant definitions out of a set of schemas and uses imports instead.
sfactor [-import common.xsd] [-out outputdir] inputdir [-license]
Validates the specified instance against the specified schema. Unlike the validate tool, svalidate uses a streaming model through which you can validate much larger instances with less memory (if the schema permits it).
svalidate [options] schema.xsd instance.xml
Validates a the specified instance against the specified schema. Compare this tool with the svalidate tool, which is useful for validating very large documents.
validate [options] schema.xsd instance.xml
The following simple example validates PurchaseOrder.xml against EasyPO.xsd.
validate ..\schemas\EasyPO.xsd PurchaseOrder.xml
In this example, MySchema imports types from another schema and also includes multiple particles defined as <xsd:any> types. The validate command here locates the external schemas for importing (providing there is network access to the schemas) and ignores the validation rule whereby multiple particles of the same qname render the schema invalid.
validate -dl -noupa ..\schemas\MySchema.xsd AnInstance.xml
Pretty prints the specified XML to the console.
xpretty [options] file.xml
Prints an XML instance from the specified global element using the specified schema.
xsd2inst schemafile.xsd -name globalElementName
The following command and output use the schema that accompanies the SubstitutionGroup sample.
xsd2inst easypo.xsd -name invoice-header
Output
<eas:invoice-header xmlns:eas="http://xmlbeans.apache.org/samples/substitutiongroup/easypo"> <eas:ship-to> <eas:name>string</eas:name> <eas:address>string</eas:address> </eas:ship-to> <eas:bill-to> <eas:name>string</eas:name> <eas:address>string</eas:address> </eas:bill-to> <!--Optional:--> <eas:product id="3"/> <!--Optional:--> <eas:comment>string</eas:comment> </eas:invoice-header>
Prints inheritance hierarchy of types defined in a schema.
xsdtree [-noanon] [-nopvr] [-noupa] [-partial] [-license] schemafile.xsd*
The following command and output use the schema that accompanies the SubstitutionGroup sample.
xsdtree easypo.xsd
Output:
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:eas="http://xmlbeans.apache.org/samples/substitutiongroup/easypo" +-xs:anyType (builtin) +-xs:anySimpleType (builtin) | +-xs:string (builtin) | +-xs:normalizedString (builtin) | +-xs:token (builtin) | +-type of color element in eas:clothing-type (enumeration) +-type of element eas:invoice-header +-type of element eas:purchase-order +-eas:product-type | +-eas:clothing-type | +-eas:book-type +-eas:name-address
Compiles a set of XSD and/or WSDL files into XMLBeans types. See xmlbean Ant Task for more complete documentation on the task.
xmlbeans-2.6.0/docs/images/conCursorTokenLocations.gif 100644 0 0 42521 11361341574 20226 0 ustar 0 0 GIF89a×÷ € € €€ €€ € €€ÀÀÀÀÜÀ¦Êð € Ö–––ÿÿÿ ÿû𠤀€€ÿ ÿ ÿÿ ÿÿ ÿ ÿÿÿÿÿ!ù , ׇ € € €€ €€ € €€ÀÀÀÀÜÀ¦Êð € Ö–––ÿÿÿ ÿû𠤀€€ÿ ÿ ÿÿ ÿÿ ÿ ÿÿÿÿÿþ H° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜ©S ÏŸ@ƒ J´¨Ñ„>*Mª´é@¦N£JJu(Ôª;¯b ªu«×¯`Ãnì*6&Ù²5Ï¢]˶íVµnQÂËr.Ý»xóÒ´«÷#ß¾#ÿL¸pFÁ†-BÀ˜ñA !s”,°±cË’1çDœ¸³çÏO j6HbiŒE;x:sÁÌ–+‹®[1é„§æ¶¹õëÙ¬q.®ý[âîÈÀeŸ=š8ñå¯W; º:]ǧ#×HÙµòéÝaþ³ö®ºvŒØU{‡Í¾têîÚ¥§>ÿÛwrúø÷ÞF˜]aÓðÉÞxù¹÷ö÷Ÿu†•ÞxëÑÖžzôõ„ße¨¡x´uèanâ·`CVß&.ßj!æÇ\qæQgS‰àEX£„î]\oá‘' Šv˜`rÞg^ƒH¢U⊠î#®ã‘QžxbˆÍ5y$EKîØ£Ž2i¢ŒDi ‹úÁÈ$y-ž¹b•þ8¦“6—`‘[Ö(]’|¾µß˜_¶Y&›zîbqu6™¨‹pÆ9Q—?ú˜"”.$ãRÎøç›‚)¢“€Î‡¨–Š^Éß—e::bŸ¬©©þ>)§˜¸ý©\¢Ub¹_‹hJôꢴžy`£†ª9e¦imJ熲ZI+³Ö†k¯·>æÜcf‹Õ¯Î‚ú)t,Njì¤6–»©°¶®‚ëŠ(%Æšj³Ô¾Ä®r~;l¾Å Y_µ˜Æy§ŠÚ,ó×nŽà^(¡ª{Šª¥¹…†i$—)!›Â벇"PưoÚ)ŸîjðÊDqv‘Æl¹\ºzÉ