[prev in list] [next in list] [prev in thread] [next in thread]
List: xmlbeans-dev
Subject: Tutorial fixes.
From: "Steven Traut" <straut () bea ! com>
Date: 2004-11-11 21:44:17
Message-ID: 4C2F1577F2EF2840A9AE9EC61860C881996658 () usseex01 ! amer ! bea ! com
[Download RAW message or body]
Partial fixes to XMLBEANS-85 on Jira \
(http://nagoya.apache.org/jira/browse/XMLBEANS-85). I've attached the Forrest XML and \
PDF output.
Here are the issues and fixes:
- missing import statements in source code -- fixed.
- generated code won't compile because easypo.xsdconfig is present -- not an issue \
for the tutorial. This would be an issue if the tutorial asked users to scomp the \
entire contents of the schemas/easypo directory; instead, the tutorial does (and \
did) tell users to compile easypo.xsd within that folder -- ignoring \
the xsdconfig.
- release readme tells users to set XMLBEANS_HOME to the release lib folder -- not an \
issue for the tutorial. I agree that this is a readme problem. I added a line to the \
tutorial that users should use the environment described in the installation topic.
- compile statement is bad. And indeed it was a copy/paste mess. I fixed it, and also \
made the command more Windows-specific (percents, semicolons, backslashes), in \
keeping with the rest of the tutorial.
This mail includes another opportunistic fix to the site.
- "V1 Javadoc" was appearing twice on the home page. I fixed this in the site.xml.
<<tutorial_getstarted.xml>> <<tutorial_getstarted.pdf>> <<site.xml>>
["tutorial_getstarted.xml" (text/xml)]
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.2//EN" \
"http://forrest.apache.org/dtd/document-v12.dtd"> <document>
<header>
<title>Tutorial: First Steps with XMLBeans</title>
</header>
<body>
<section>
<title/>
<p>This tutorial introduces XMLBeans basics. Through it, you'll get a \
hands on view of
two of the three technologies that make up version 1 of XMLBeans: \
strongly-typed access to
XML through compiled schema and type-agnostic access to XML through \
the XML cursor.
This tutorial describes what XMLBeans is and introduces a few of the \
tools that come with an XMLBeans installation.</p>
<p>To get started, you'll need the following:</p>
<ul>
<li>JDK 1.4 for version 1 XMLBeans releases. You can download the JDK \
<jump \
href="http://java.sun.com/j2se/1.4.2/download.html">here</jump>.</li>
<li>An XMLBeans version 1 installation. If you don't have this yet, \
you'll find
installation instructions at <link \
href="conInstallGuide.html">Installing XMLBeans</link>.</li>
<li>An environment set up according to what's described in <link \
href="conInstallGuide.html">Installing XMLBeans</link>.</li>
<li>An editor for writing Java code. This could be a text editor or \
your favorite Java IDE.</li>
</ul>
<p>You'll create a few files as part of this tutorial. Start out by \
creating a new
tutorials directory just under your XMLBEANS_HOME directory. This \
will hold the
files you create in the course of this tutorial. While you're at it, \
create the
following subdirectories under the tutorials directory: classes, \
instances, src,
lib. If you're working with XMLBeans version 1.0.3, your hierarchy \
should look something like this:</p>
<source>xmlbeans-1.0.3
...
tutorials
gettingstarted
classes
instances
lib
src</source>
</section>
<section>
<title>Get Acquainted with the Basics</title>
<p>XMLBeans version 1 includes multiple related technologies for handling \
XML. In a
nutshell, XMLBeans offers three complementary technologies:</p>
<ul>
<li>A schema-oriented way to view XML instances through Java types \
based on the schema.</li>
<li>A schema-agnostic way to traverse the full XML infoset.</li>
<li>A schema object model through which, in Java code, you can \
examine a compiled
XML schema. (Note: this aspect of XMLBeans is not covered in this \
tutorial. For more information, see <link
\
href="../docs/guide/conIntroToTheSchemaTypeSystem.html">Introduction to the Schema \
Type System.</link> </li>
</ul>
<p>There's much more, but that's a start. Each of these three pieces is \
useful for
different goals, and you may find yourself writing code that uses all \
three in the
same application. The rest of this tutorial will introduce you to \
these technologies.</p> </section>
<section>
<title>Getting Started with Handling XML Through Schema</title>
<p>One of the things XMLBeans does best is provide a way for you to \
handle XML by using
a schema to which the XML conforms. With XMLBeans you can compile one \
or more schema
(XSD) files to generate Java types. By binding XML instance documents \
to these Java
types, you provide yourself a way to access the instances in Java in \
a schema-oriented way.</p>
<p>Try this now with XML you got when you installed XMLBeans. To start \
out, open a
command prompt and cd to the directory containing your XMLBeans \
installation. If you
installed version 1.0.3 to your root directory, you'd do this on \
Windows:</p> <source>cd \xmlbeans-1.0.3</source>
<p>If you followed the installation instructions at Installing XMLBeans, \
you should be
able to execute the scripts you got in the \bin directory. Use one of \
these now —
xpretty — to take a look at easypo schema contained in easypo.xsd, \
like so (if
you're using a UNIX OS this script isn't available, so you'll need to \
open the file in an editor):</p>
<source>xpretty schemas\easypo\easypo.xsd</source>
<p>After the copyright text, you should see the following:</p>
<source><xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:po="http://openuri.org/easypo"
targetNamespace="http://openuri.org/easypo"
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" maxOccurs="1"/> </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:attribute name="age" type="xs:int"/>
<xs:attribute name="moo" type="xs:int" \
default="100"/>
<xs:attribute name="poo" type="xs:int" \
fixed="200"/> </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:decimal"/>
<xs:element name="quantity" type="xs:integer"/>
</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></source>
<p>If you don't know anything about schema, here are a few basics for this one:</p>
<ul>
<li>This schema is a blueprint, defining the rules for creating a \
certain "shape" of XML for purchase orders.</li>
<li>The purchase order XML defined here would have a \
<code><purchase-order></code>
element that has four immediate children: \
<code><customer></code>,
<code><date></code>, <code><line-item></code>, and \
<code><shipper></code> — in that sequence.</li>
<li>Three of the four child elements have their own children in a \
particular structure,
as defined in the schema's respective \
<code><complexType></code> elements.</li> </ul>
<p>Now take a look at an XML document based on this schema. Copy the \
following XML from
this page into a new XML file called easypo.xml, then put the file in \
the
tutorials\gettingstarted\instances directory you created at the \
beginning of this tutorial.</p>
<source><purchase-order \
xmlns="http://openuri.org/easypo"> <customer>
<name>Gladys Kravitz</name>
<address>Anytown, PA</address>
</customer>
<date>2003-01-07T14:16:00-05:00</date>
<line-item>
<description>Burnham's Celestial Handbook, Vol 1</description>
<per-unit-ounces>5</per-unit-ounces>
<price>21.79</price>
<quantity>2</quantity>
</line-item>
<line-item>
<description>Burnham's Celestial Handbook, Vol 2</description>
<per-unit-ounces>5</per-unit-ounces>
<price>19.89</price>
<quantity>2</quantity>
</line-item>
<shipper>
<name>ZipShip</name>
<per-ounce-rate>0.74</per-ounce-rate>
</shipper>
</purchase-order></source>
<p>This XML represents a purchase order in through which Gladys, an \
amateur astronomer,
is buying two books to use as references in her stargazing (along \
with an extra copy
of each for her niece). Because this XML is an instance of the \
schema, you'll
recognize the <code><purchase-order></code> element and its \
children,
<code><customer></code>, <code><date></code>, \
<code><line-item></code>, and <code><shipper></code>.</p>
<p>Now to try these examples out with XMLBeans. Among the tools included \
with XMLBeans
is scomp, a script that executes the schema compiler (part of the \
XMLBeans API) to
compile a schema or directory of schemas. Use scomp to compile the \
easypo schema. On
Windows, use the following command (this script is also available on \
UNIX):</p>
<source>scomp -out tutorials\gettingstarted\lib\easypo.jar \
schemas\easypo\easypo.xsd</source>
<p>You'll end up with easypo.jar in the lib directory of your tutorial \
hierarchy.</p> <section>
<title>Results of Compiling the Schema</title>
<p>[This section describes the interfaces generated by the schema \
compiler. If
you're familiar with this want to skip to writing Java code, go \
to <link href="#writing_code_that_uses_types">Writing Code that Uses Generated \
Types</link>.]</p>
<p>The schema compiler's output is designed not only to provide a \
JavaBeans-oriented
view of your schema, but to anticipate the shortcuts you're \
likely to want. If
you compare the contents of easypo.xsd with the Java types \
generated by
compiling it, you'll see obvious parallels. For each of the \
elements and schema
types defined in the schema, the schema compiler has generated \
Java types. The
package name corresponds to the schema's namespace URI.</p>
<p>For example, take another look at the <purchase-order> \
element defined in the schema:</p>
<source><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" maxOccurs="1"/> </xs:sequence>
</xs:complexType>
</xs:element></source>
<p>This snippet defines the <code><purchase-order></code> \
element as having a
"local" complex type (also known as an "anonymous" complex type). \
This type
includes a sequence of child elements (in the schema world,
<code><sequence></code> is a "compositor" and each \
<code><element></code> is a
"particle"). The <code><date></code> element is specified \
as an xs:dateTime, a
built-in type defined by the W3C's schema data type \
specification; the other
three elements are complex types defined elsewhere in this \
schema.</p> <section>
<title>Options for Accessing Elements of Built-In Schema \
Types</title>
<p>To represent the <code><purchase-order></code> element, \
the
schema compiler has generated a <code>PurchaseOrder</code> \
interface that
extends <code>java.lang.Object</code> and <link \
href="http://xmlbeans.apache.org/docs/reference/org/apache/xmlbeans/XmlObject.html"> \
<code>org.apache.xmlbeans.XmlObject</code>
</link>. However, you'll find that this interface is actually \
contained
within a <code>PurchaseOrderDocument</code> interface. \
XMLBeans does this
for <code>"global"</code> element and attributes \
— those defined at the
top level of the schema. This is to provide you with a way to \
get and set
the global item as a whole piece, which would be difficult to \
do if it
weren't contained by anything. In other words, you need a \
type on which to methods such as <code>getPurchaseOrder</code> and
<code>setPurchaseOrder</code> and this \
<code>"Document"</code> interface fills that role.</p>
<p> For each of <code><purchase-order></code>'s four child
elements, the <code>PurchaseOrder</code> interface exposes \
accessors
according to JavaBeans conventions. For example, for the
<code><date></code> element you have the following:</p>
<source>public abstract java.util.Calendar getDate()
public abstract void setDate ( java.util.Calendar )</source>
<p>This is one of two ways that the schema compiler provides for \
access to the
<code><date></code> element — a more convenient, \
Java-native
way, one might say. These accessors are a kind of convenience \
pair (you're
likely to want a <code>Calendar</code> instance when working \
with a date).
However, because the <code><date></code> element's \
type,
<code>xs:dateTime</code>, is a built-in schema type, the \
schema compiler
provides accessors that get and set its value with another \
Java type that XMLBeans defines:</p>
<source>public abstract org.apache.xmlbeans.XmlDateTime \
xgetDate() public abstract void xsetDate( org.apache.xmlbeans.XmlDateTime )</source>
<p>
<link \
href="http://xmlbeans.apache.org/docs/reference/org/apache/xmlbeans/XmlDateTime.html">
<code>XmlDateTime</code>
</link> can be seen as a Rosetta Stone. With it, you can get \
and set the
element's value using <link \
href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/Calendar.html"> \
<code>java.util.Calendar</code>
</link>, <link \
href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/Date.html"> \
<code>java.util.Date</code>
</link>, and <link \
href="http://xmlbeans.apache.org/docs/reference/org/apache/xmlbeans/GDate.html"> \
<code>org.apache.xmlbeans.GDate</code>
</link>. (For a full list of how built-in schema types are \
mapped to Java types by the compiler, see <link
\
href="http://xmlbeans.apache.org/docs/guide/conXMLBeansSupportBuiltInSchemaTypes.html">XMLBeans
Support for Built-In Schema Types</link>.) </p>
</section>
<section>
<title>Access for Elements of User-Defined Schema Types</title>
<p>For the three elements whose types are defined <em>within</em> \
the schema,
the compiler generates separate Java types and uses these in \
accessors — as
below for the <code><customer></code> element's
<code>customer</code> type.</p>
<source>public abstract org.openuri.easypo.Customer getCustomer()
public abstract void setCustomer( org.openuri.easypo.Customer )</source>
<p>In other words you can call <code>getCustomer</code> to \
retrieve its
<code>Customer</code> instance, then update the instance's \
contents — which
is how you update the content of the \
<code><customer></code> element it represents. </p>
<p>Along the same lines, you get a convenience method for complex \
types like <code>customer</code>, like so:</p>
<source>public abstract org.openuri.easypo.Customer \
addNewCustomer()</source>
<p>Through an <code>add*</code> method such as this one, you can \
add a new <code><customer></code> element to the
<code><purchase-order></code> element. The method \
returns a
<code>Customer</code> instance so that you can update the new \
element's contents. </p>
<p>Other convenience methods are provided for elements and \
attributes that
schema defines as optional. The <code><shipper></code> \
element
is optional because the schema specifies its \
<code>minOccurs</code>
attribute value as <code>0</code> (the default value for this \
attribute is
<code>1</code>). As a result, the element need not exist in \
the XML in order
for the instance to be valid. To find out if it's there and \
to remove it if it is, you get these methods:</p>
<source>public boolean isSetShipper ( )
public abstract void unsetShipper ( )</source>
</section>
<section>
<title>Arrays for Accessing Elements That May Occur More Than \
Once</title> <p>Another optional element defined by the schema is
<code><line-item></code>. However, there's an important
difference for <code><line-item></code> — its
<code>maxOccurs</code> attribute's value is \
"unbounded," meaning it may occur multiple times as a child of
<code><purchase-order></code> (like \
<code>minOccurs</code>,
the default of <code>maxOccurs</code> is <code>1</code>). A \
common Java way
to handle multiple instances of the same type is through an \
array of that
type — and that's exactly what the schema compiler gives \
you:</p> <source>// Get or set the whole array.
public abstract org.openuri.easypo.LineItem[] getLineItemArray ( )
public abstract void setLineItemArray ( org.openuri.easypo.LineItem[] )
// Get or set a single item.
public abstract org.openuri.easypo.LineItem getLineItemArray ( int )
public abstract void setLineItemArray( int, org.openuri.easypo.LineItem )
// Add or remove an item.
public abstract org.openuri.easypo.LineItem insertNewLineItem( int )
public abstract void removeLineItem( int )
// Get the array's size (without having to get the array, then call .length).
public abstract int sizeOfLineItemArray()</source>
<p>Finally, you'll notice that the schema compiler has generated \
a <code>field</code>:</p>
<source>public static final org.apache.xmlbeans.SchemaType \
type</source>
<p>You can use this field for access to a <link \
href="http://xmlbeans.apache.org/docs/reference/org/apache/xmlbeans/SchemaType.html"> \
<code>SchemaType</code>
</link> instance that represents the underlying schema type \
itself. This
will be covered in the last part of this tutorial.</p>
<note>For more information about the types generated from \
schema, see <link href="../docs/guide/conJavaTypesGeneratedFromUserDerived.html">Java \
Types Generated from User-Derived Schema Types</link>. To learn more about generated \
methods, see <link href="../docs/guide/conMethodsForGeneratedJavaTypes.html">Methods \
for Types Generated from Schema</link>. Also, XMLBeans provides its own Java types \
for built-in schema data types such as <code>xs:dateTime</code>, \
<code>xs:decimal</code>, and so on. To read more about these, see <link \
href="../docs/guide/conXMLBeansSupportBuiltInSchemaTypes.html">XMLBeans Support for \
Built-In Schema Types</link>.</note> </section>
</section>
<anchor id="writing_code_that_uses_types"/>
<section>
<title>Writing Code that Uses Generated Types</title>
<p>You're going to write a bit of code to add a new line item to the \
purchase order.
It turns out that Gladys wants to add another book to her order. \
Your code will
accept the existing order along with raw data for the new item, \
then add the item and return the updated XML.</p>
<p>Start out by creating a POUpdater.java file in the
<code>tutorials\gettingstarted\src</code> directory. Add the \
following code to that file:</p>
<source>import java.io.*;
import java.math.*;
import org.apache.xmlbeans.*;
import org.apache.easypo.*;
public class POUpdater
{
private static String addLineItem(File purchaseOrder, String itemDescription,
String perUnitOuncesString,
String itemPriceString, String \
itemQuantityString) {
// Bind the incoming XML to an XMLBeans type.
PurchaseOrderDocument poDoc = null;
try
{
poDoc = PurchaseOrderDocument.Factory.parse(purchaseOrder);
} catch (XmlException e)
{
e.printStackTrace();
} catch (IOException e)
{
e.printStackTrace();
}
return poDoc.toString();
}
}</source>
<p>So far, the <code>addLineItem</code> method binds the incoming XML \
to an XMLBeans
type generated by compiling the schema. This snippet creates a \
method that
receives a <code>File</code> instance representing the purchase \
order XML, as
well as strings containing the raw data that will comprise the \
new item added.
You bind the XML <em>document</em> — the root element and its \
children — to the
<code>PurchaseOrderDocument</code> interface. This interface, \
like all types
extending <link \
href="http://xmlbeans.apache.org/docs/reference/org/apache/xmlbeans/XmlObject.html"> \
<code>XmlObject</code>
</link> (including all types generated from schema), provides a
<code>Factory</code> class with which to create new instances. \
The
<code>Factory</code> class provides various versions of the \
<code>parse</code>
method, each receiving XML source as a different Java type.</p>
<p>The method's next bit of code, show below, converts the incoming \
raw data into
types that can be used when creating the new \
<code><line-item></code> element.
It then adds the new element and sets that element's children's \
values. Remember
that, in XMLBeans, you get at the type representing a global \
element by going
through the <code>"Document"</code> type that contains \
it — here, with the <code>getPurchaseOrder</code> method. </p>
<source>BigDecimal perUnitOunces = new \
BigDecimal(perUnitOuncesString); BigDecimal itemPrice = new \
BigDecimal(itemPriceString); BigInteger itemQuantity = new \
BigInteger(itemQuantityString);
LineItem newItem = poDoc.getPurchaseOrder().addNewLineItem();
newItem.setDescription(itemDescription);
newItem.setPerUnitOunces(perUnitOunces);
newItem.setPrice(itemPrice);
newItem.setQuantity(itemQuantity);</source>
<p>That's pretty much all there is to it. The JavaBeans-style access \
provided by
compiling your schema greatly simplifies your access to XML \
instances based on the schema. </p>
<p>Here's a full version of the <code>POUpdater</code> class, with \
the
<code>addLineItem</code> method accessible via a \
<code>main</code> method.</p> <source>import java.io.*;
import java.math.*;
import org.apache.xmlbeans.*;
import org.apache.easypo.*;
public class POUpdater
{
public static void main(String[] args)
{
File poXmlFile = new File(args[0]);
String updatedPoXml = addLineItem(poXmlFile, args[1], args[2],
args[3], args[4]);
System.out.println(updatedPoXml);
}
private static String addLineItem(File purchaseOrder, String itemDescription,
String perUnitOuncesString,
String itemPriceString, String \
itemQuantityString) {
PurchaseOrderDocument poDoc = null;
try
{
// Bind the incoming XML to an XMLBeans type.
poDoc = PurchaseOrderDocument.Factory.parse(purchaseOrder);
} catch (XmlException e)
{
e.printStackTrace();
} catch (IOException e)
{
e.printStackTrace();
}
// Convert incoming data to types that can be used in accessors.
BigDecimal perUnitOunces = new BigDecimal(perUnitOuncesString);
BigDecimal itemPrice = new BigDecimal(itemPriceString);
BigInteger itemQuantity = new BigInteger(itemQuantityString);
// Add the new <line-item> element.
LineItem newItem = poDoc.getPurchaseOrder().addNewLineItem();
newItem.setDescription(itemDescription);
newItem.setPerUnitOunces(perUnitOunces);
newItem.setPrice(itemPrice);
newItem.setQuantity(itemQuantity);
return poDoc.toString();
}
}</source>
<p>Now, compile the new class with a command such as the following \
(the line is broken for readability):</p>
<source>javac -classpath \
%XMLBEANS_HOME%\lib\xbean.jar;tutorials\gettingstarted\lib\easypo.jar \
-d tutorials\gettingstarted\classes \
tutorials\gettingstarted\src\POUpdater.java</source>
<p>After you compile, you can try out the class with the following \
command (again, broken for readability):</p>
<source>java -cp \
tutorials\gettingstarted\classes;%XMLBEANS_HOME%\lib\xbean.jar;tutorials\gettingstarted\lib\easypo.jar \
POUpdater tutorials\gettingstarted\instances\easypo.xml "a new item" 5.0 \
20.00 6</source>
<p>The output should look like the instance output above, but with \
the following
added as the last <code><line-item></code> element, \
immediately before the <code><shipper></code> element. </p>
<source><line-item>
<description>Backyard Astronomer's Guide, The</description>
<per-unit-ounces>5.0</per-unit-ounces>
<price>49.95</price>
<quantity>2</quantity>
</line-item></source>
<p>Obviously, you need a schema to use this aspect of XMLBeans. But \
you may find
yourself creating a schema where you only have instances so that \
you can compile
it to generate those Java types — just to make your life a \
little easier.</p> </section>
</section>
<section>
<title>Getting Started with the XML Cursor</title>
<p>The XML cursor — represented in the API by the <link \
href="http://xmlbeans.apache.org/docs/reference/org/apache/xmlbeans/XmlCursor.html"> \
<code>org.apache.xmlbeans.XmlCursor</code>
</link> interface — is designed to (among other things) complement \
the
JavaBeans-style access you get from types generated by compiling \
schema. The cursor
provides the ability to move over the XML in a more fine-grained \
manner. For example, in the preceding code you added a new
<code><line-item></code> element, but you had no control over \
where
the new element went. XMLBeans just inserted it as the last
<code><line-item></code>. The simplicity provided by get/set \
pairs is
clearly an advantage with the Java types you get from schema, but \
when you care
about finer control — such as element order — then turn to \
<code>XmlCursor</code>. </p>
<p>You might say that <code>XmlCursor</code> provides a schema-agnostic \
view of the XML.
From a cursor's perspective, the XML is a series of <em>tokens</em>.
These tokens are divided into categories called <em>token types</em>
represented by constants of <link \
href="http://xmlbeans.apache.org/docs/reference/org/apache/xmlbeans/XmlCursor.TokenType.html">
<code>org.apache.xmlbeans.XmlCursor.TokenType</code>
</link>. Token types include <code>START</code> (for the beginning of \
an element),
<code>END</code> (for its end), <code>ATTR</code> (for an attribute), \
and
<code>TEXT</code> (for an element's text content). With a cursor, you \
navigate through XML by moving the cursor from token to token.</p>
<section>
<title>Adding a New <line-item> Element, Cursor-Style </title>
<p>In this section you'll insert the same new \
<code><line-item></code>
element, but with care this time to ensure that it's in the right \
place in the
list, alphabetically. For simplicity's sake, assume that the
<code><line-item></code> elements in the document you \
receive are
already in alphabetical order (which, it so happens, they are). \
You just need to make sure the addition follows suit.</p>
<p>Create a new method called <code>addLineItemWithCursor</code>. \
You'll use this as
an alternative to the previous method. As in the \
<code>addLineItem</code>
method, you'll need to parse the incoming XML into the types you \
generated, so
your new method should start out looking like this:</p>
<source>private static String addLineItemWithCursor(File \
purchaseOrder, String itemDescription, String perUnitOunces, String itemPrice, \
String itemQuantity) {
PurchaseOrderDocument poDoc = null;
try
{
poDoc = PurchaseOrderDocument.Factory.parse(purchaseOrder);
} catch (XmlException e)
{
e.printStackTrace();
} catch (IOException e)
{
e.printStackTrace();
}
PurchaseOrderDocument.PurchaseOrder po = poDoc.getPurchaseOrder();
}</source>
<p>Next, you'll need to add something through which you can check for \
alphabet
order. For this, you can use a class that implements <link \
href="http://java.sun.com/j2se/1.4.2/docs/api/java/text/Collator.html"> \
<code>java.text.Collator</code>
</link>. As it turns out, <link \
href="http://java.sun.com/j2se/1.4.2/docs/api/java/text/RuleBasedCollator.html"> \
<code>java.text.RuleBasedCollator</code>
</link> does just what you need by comparing words to find out if \
one should
precede the other. You'll instantiate a <code>RuleBasedCollator \
</code> with the following code:</p>
<source>RuleBasedCollator collator =
(RuleBasedCollator)Collator.getInstance(new Locale("en", \
"US", ""));</source>
<p>Now it's time to get started with the cursor. You can add a new \
cursor to any
XMLBeans type that extends <code>XmlObject</code> — including \
the generated
types that represent your schema. When you add a cursor with the
<code>newCursor</code> method, the cursor is created at the \
beginning of the XML
represented by the type on which you're calling the method. For \
example, the
following line of code will create a cursor that immediately \
precedes the XML represented by <code>PurchaseOrder</code>:</p>
<source>XmlCursor cursor = po.newCursor();</source>
<p>In other words, after this code, the cursor will immediately \
precede the
<code><purchase-order></code> element — it will be at \
that element's <code>START</code> token. The
<code><purchase-order></code> element has an \
<code>xmlns</code>
attribute, so if you called <link \
href="http://xmlbeans.apache.org/docs/reference/org/apache/xmlbeans/XmlCursor.html#toNextToken()">
<code>cursor.toNextToken()</code>
</link>, you would move the cursor to an <code>ATTR</code> token \
that represents the attribute, as illustrated here.</p>
<p>
<img src="../images/tokentypes.jpg" width="644" height="212" \
alt="Token types"/> </p>
<p>But for for the moment, the code will leave the cursor where it \
is. Instead,
you'll call another method to get the URI for the default \
namespace — you're
going to need that when adding new elements, as you'll see.</p>
<source>String namespaceUri = \
cursor.namespaceForPrefix("");</source>
<p>To do the real work, you'll write code to get, JavaBeans-style, \
the array
representing <code><line-item></code> elements and loop \
through
the array to find the first line item whose description belongs \
<em>after</em>
the one you want to insert. Then your code will insert the new \
line item before the one it found.</p>
<p>In particular, you'll reassign the existing cursor instance to a \
new cursor at
the <code><line-item></code> element before which you want \
to insert.</p> <source>cursor = lineItem.newCursor();</source>
<p>Then you'll begin a new element there; giving the new element the \
default
namespace URI will ensure that the element belongs to the same \
namespace as the XML around it.</p>
<source>cursor.beginElement("line-item", \
namespaceUri);</source>
<p>The <link \
href="http://xmlbeans.apache.org/docs/reference/org/apache/xmlbeans/XmlCursor.html#beginElement(java.lang.String,%20java.lang.String)">
<code>beginElement</code>
</link> method creates a new element where the cursor is (if \
doing so will
result in well-formed XML) and leaves the cursor between the new \
element's <code>START</code> and <code>END</code> tokens. </p>
<p>Finally, your code will populate the new \
<code><line-item></code>
element with child elements through further calls to \
<code>beginElement</code>
and by inserting text for the elements' values. Here's snippet to \
show how this works:</p>
<source>cursor.beginElement("description", namespaceUri);
cursor.insertChars(itemDescription);
cursor.toNextToken();
cursor.beginElement("per-unit-ounces", namespaceUri);
// ... and so on for the other children...</source>
<p>The following illustrates the shifting and moving of tokens that \
occurs between
inserting a new cursor and beginning a new element.</p>
<p>
<img src="../images/tokentypes_newcursor.jpg" width="476"
height="153" alt="Inserting a new cursor."/>
</p>
<p>
<img src="../images/beginelement.jpg" width="419" height="166" \
alt="Beginning a new element."/> </p>
<p>
<img src="../images/after_beginelement.jpg" width="449"
height="129" alt="After the new element begins."/>
</p>
<p>Cursor operations are like this. You move the cursor from token to \
token as if
from one train car to another. Copying, moving or removing \
elements shifts
tokens to make room for others or to close up a space left \
behind.</p> <note>The token type names (<code>START</code>,
<code>END</code>, <code>ATTR</code>, and so on) will tempt \
you to equate
tokens with actual parts of the XML markup — resist the \
temptation. The
tokens are abstractions, not tags. For example, an element \
expressed in an instance document as <code><foo
bar="baz"/></code> will have a \
<code>START</code>,
<code>ATTR</code>, and <code>END</code> token even though it \
does not have an end tag. You can learn more about token types at <link \
href="../docs/guide/conUnderstandingXMLTokens.html">Understanding XML \
Tokens</link>.</note> <p>Here's the method's full code:</p>
<source>private static String addLineItemWithCursor(File \
purchaseOrder, String itemDescription, String perUnitOunces, String itemPrice, \
String itemQuantity) {
PurchaseOrderDocument poDoc = null;
try
{
poDoc = PurchaseOrderDocument.Factory.parse(purchaseOrder);
} catch (XmlException e)
{
e.printStackTrace();
} catch (IOException e)
{
e.printStackTrace();
}
PurchaseOrderDocument.PurchaseOrder po = poDoc.getPurchaseOrder();
// Set up the collator for alphabetizing.
RuleBasedCollator collator =
(RuleBasedCollator)Collator.getInstance(new Locale("en", \
"US", "")); XmlCursor cursor = po.newCursor();
// Get the document's URI so you can use it to insert.
String namespaceUri = cursor.namespaceForPrefix("");
// Get the array of <line-item> elements.
LineItem[] lineItems = po.getLineItemArray();
// Loop through the element array to discover where to insert the new one.
for (int i = 0; i < lineItems.length; i++)
{
LineItem lineItem = lineItems[i];
// Find out if the new line item's description belongs before the
// current line item's.
int comparison = collator.compare(itemDescription, \
lineItem.getDescription());
// If the comparison returns -1, then insert the new line item (and
// its children) before the current one.
if (comparison < 0)
{
cursor = lineItem.newCursor();
// Begin the new <line-item> element.
cursor.beginElement("line-item", namespaceUri);
// Begin the new <description> element and insert its text value.
cursor.beginElement("description", namespaceUri);
cursor.insertChars(itemDescription);
// Move on and do the same for the other elements.
cursor.toNextToken();
cursor.beginElement("per-unit-ounces", namespaceUri);
cursor.insertChars(perUnitOunces);
cursor.toNextToken();
cursor.beginElement("prices", namespaceUri);
cursor.insertChars(itemPrice);
cursor.toNextToken();
cursor.beginElement("quantity", namespaceUri);
cursor.insertChars(itemQuantity);
break;
}
}
// Speed the cursor's garbage collection and return the updated XML.
cursor.dispose();
return poDoc.toString();
}</source>
<p>Before testing, you'll want to update your main method so that it \
calls the
<code>addLineItemCursor</code> method rather than the \
<code>addLineItem</code> method you used earlier.</p>
<source>public static void main(String[] args)
{
File poXmlFile = new File(args[0]);
// String updatedPoXml = addLineItem(poXmlFile, args[1], args[2],
// args[3], args[4]);
String updatedPoXml = addLineItemWithCursor(poXmlFile, args[1], args[2],
args[3], args[4]);
System.out.println(updatedPoXml);
} </source>
<p>Finally, before compiling, you'll need to add two more import \
statements to support the alphabetization code:</p> <source>import java.text.*;
import java.util.*;</source>
<p>Test the <code>POUpdater</code> class just as you did before. This \
time, you
should see the new <code><line-item></code> element added \
as the first in the set, rather than at the end.</p>
<p>Before moving on, you should give some thought to another aspect \
of working with
cursors. The cursor's support for changing the XML outside any \
schema
constraints also means that, without care, you can stray far from \
schema validity. If validity matters, be sure to consider calling the <link \
href="http://xmlbeans.apache.org/docs/reference/org/apache/xmlbeans/XmlObject.html#validate()">
<code>validate</code>
</link> method before passing the edited XML along.</p>
<note>To learn more about using the <code>XmlCursor</code> \
interface, see <link href="../docs/guide/conNavigatingXMLwithCursors.html">Navigating \
XML with Cursors</link>.</note> </section>
</section>
<section>
<title>Where to Go from Here</title>
<ul>
<li>Be sure to check out the <link
\
href="http://xmlbeans.apache.org/documentation/index.html">XMLBeans \
documentation</link>.</li>
<li>The <link \
href="http://xmlbeans.apache.org/resources/index.html">XMLBeans
Resources</link> page provides links to lots of articles.</li>
</ul>
</section>
</body>
</document>
["tutorial_getstarted.pdf" (application/octet-stream)]
["site.xml" (text/xml)]
<?xml version="1.0"?>
<!--
Forrest site.xml
This file contains an outline of the site's information content. It is used to:
- Generate the website menus (though these can be overridden - see docs)
- Provide semantic, location-independent aliases for internal 'site:' URIs, eg
<link href="site:changes"> links to changes.html (or ../changes.html if in
subdir).
- Provide aliases for external URLs in the external-refs section. Eg, <link
href="ext:cocoon"> links to http://xml.apache.org/cocoon/
See http://xml.apache.org/forrest/linking.html for more info
-->
<site label="XMLBeans" xmlns="http://apache.org/forrest/linkmap/1.0">
<main_index_file tab="home">
<index href="index.html"/>
</main_index_file>
<download-tab label="Download" href="sourceAndBinaries/" tab="download">
<index href="index.html"/>
<releases label="Releases"
href="index.html#XMLBeans+Binary+and+Development+Kit"
description="Download an XMLBeans release." tab="download"/>
<source label="Source Code" href="index.html#XMLBeans+Source"
description="Get the source code." tab="download"/>
<install label="Installing XMLBeans" \
href="../documentation/conInstallGuide.html" description="Install XMLBeans"/> \
</download-tab> <documentation-tab label="Documentation" href="documentation/" \
tab="documentation"> <index href="index.html"/>
<tutorial label="Tutorial: First Steps" href="tutorial_getstarted.html" \
description="Write some XMLBeans code."/>
<faq label="FAQ" href="http://wiki.apache.org/xmlbeans/XmlBeansV1Faq" \
description="View Frequently Asked Questions"/>
<userdoc label="User Guide" \
href="index.html#XMLBeans+Version+1+User+Documentation" description="Check out the \
user guide."/>
<userdoc label="V1 Javadoc" href="../docs/reference/index.html" \
description="Look over references."/>
<userdoc label="V2 Javadoc" href="../docs/v2/reference/index.html" \
description="Look over references."/>
<samples label="Sample Code" href="../samples/index.html" \
description="Download sample code."/>
<install label="Installing XMLBeans" href="conInstallGuide.html" \
description="Install XMLBeans"/>
<wiki label="Wiki Pages" href="http://wiki.apache.org/xmlbeans/" \
description="XmlBeans Wiki pages"/> </documentation-tab>
<samples-tab label="Samples" tab="samples">
<index href="samples/index.html"/>
<samplesList label="Samples List" description="View the list of available \
samples.">
<sample label="MixedContent" href="samples/MixedContent.html" \
tab="samples"/>
<sample label="OrderMatters" href="samples/OrderMatters.html" \
tab="samples"/>
<sample label="SchemaEnum" href="samples/SchemaEnum.html" tab="samples"/>
<sample label="SubstitutionGroup" href="samples/SubstitutionGroup.html" \
tab="samples"/>
<sample label="DateTime" href="samples/DateTime.html" tab="samples"/>
<sample label="SampleTemplate" href="samples/SampleTemplate.html" \
tab="samples"/> </samplesList>
</samples-tab>
<community-tab label="Community" href="community/" tab="community">
<index href="index.html"/>
<whoWeAre label="Who We Are" href="index.html#Who+we+are" description="See \
the list of committers"/>
<mailingLists label="Mailing Lists" href="index.html#Mailing+Lists" \
description="Get mailing list information"/> </community-tab>
<project-tab label="Project" href="projectManagement/" tab="project">
<index href="index.html"/>
<version1 label="About Version 1" \
href="index.html#XMLBeans+Version+1+Project+Management" description="Read a note on \
the progress of XMLBeans Version 1"/> <version2 label="About Version 2 Plans"
href="index.html#XMLBeans+Version+2+Project+Management" description="Read \
information on the progress of XMLBeans Version 2"/>
<bugs label="Bug Tracking" href="index.html#XMLBeans+Bug+Lists" \
description="Find or log XMLBeans bugs"/> <!--
<proposal label="Initial Proposal"
href="http://nagoya.apache.org/wiki/apachewiki.cgi?XmlBeansProposal" \
description="Read the original XMLBeans project proposal"/>
-->
<roadmap label="XMLBeans Road Map"
href="http://nagoya.apache.org/wiki/apachewiki.cgi?XmlBeansRoadMap" \
description="Read ideas for future evolution"/> </project-tab>
<resources-tab label="Resources" href="resources/" tab="resources">
<index href="index.html"/>
<tools label="Tools" href="index.html#XMLBeans+Tools" description="Tools for \
working with XMLBeans."/>
<articles label="Articles" href="index.html#XMLBeans+Articles" \
description="Articles about or related to XMLBeans."/>
<books label="Books" href="index.html#XMLBeans+Books" description="Books \
about XMLBeans"/> </resources-tab>
<home label="Home" href="" tab="home">
<index href="index.html"/>
<learn label="Learn About XMLBeans">
<index label="Overview" href="index.html" description="Welcome to \
XMLBeans"/>
<faq label="FAQ" href="http://wiki.apache.org/xmlbeans/XmlBeansV1Faq" \
description="View Frequently Asked Questions"/> <userdoc label="Tutorial: First \
Steps"
href="documentation/tutorial_getstarted.html" description="Write some \
XMLBeans code."/>
<userdoc label="V1 Javadoc" href="docs/reference/index.html" \
description="Look over references."/>
<userdoc label="V2 Javadoc" href="docs/v2/reference/index.html" \
description="Look over references."/>
<sample label="Samples" href="samples/index.html" description="See a list \
of samples for download."/> <explanation label="An Explanation"
href="http://nagoya.apache.org/wiki/apachewiki.cgi?XmlBeansExplanation" \
description="Read about the rationale for XMLBeans"/> </learn>
<download label="Get XMLBeans">
<releases label="Releases"
href="sourceAndBinaries/index.html#XMLBeans+Binary+and+Development+Kit" \
description="Download an XMLBeans release."/>
<source label="Source Code" \
href="sourceAndBinaries/index.html#XMLBeans+Source" description="Get the source \
code."/>
<install label="Installing XMLBeans" \
href="documentation/conInstallGuide.html" description="Install XMLBeans"/> \
</download> <projectinfo label="Get Project Information">
<whoWeAre label="Who We Are" href="community/index.html#Who+we+are" \
description="See the list of committers"/>
<mailingLists label="Mailing Lists" \
href="community/index.html#Mailing+Lists" description="Get mailing list \
information"/> <!-- <proposal label="Initial Proposal"
href="http://nagoya.apache.org/wiki/apachewiki.cgi?XmlBeansProposal" \
description="Read the original XMLBeans Project Proposal"/>
-->
<bugs label="Bug Tracking" \
href="projectManagement/index.html#XMLBeans+Bug+Lists" description="Find or log \
XMLBeans bugs"/> <!--
<version1 label="About Version 1"
href="projectManagement/index.html#XMLBeans+Version+1+Project+Management" \
description="Read a note on the progress of XMLBeans Version 1"/>
-->
<version2 label="Version 2 Plans"
href="projectManagement/index.html#XMLBeans+Version+2+Project+Management" \
description="Read about the progress of XMLBeans Version 2"/> <!--
<todo label="To Do" \
href="http://nagoya.apache.org/wiki/apachewiki.cgi?XMLBeansToDo" description="Read \
action items, mostly regarding incubation exit criteria"/>
-->
</projectinfo>
</home>
<all>
<whole_site_html label="Whole Site HTML" href="site.html"/>
<whole_site_html label="Whole Site PDF" href="site.pdf"/>
</all>
<external-refs>
<xml.apache.org href="http://xml.apache.org/">
<forrest href="forrest/">
<validation href="validation.html"/>
<webapp href="your-project.html#webapp"/>
<document-v12 href="document-v12.html"/>
</forrest>
<cocoon href="cocoon/"/>
</xml.apache.org>
<mailsubuser label="XmlBeans User List Subscribe" \
href="mailto:user-subscribe@xmlbeans.apache.org"/>
<mailunsubuser label="XmlBeans User List UnSubscribe" \
href="mailto:user-unsubscribe@xmlbeans.apache.org"/>
<mailsubdev label="XmlBeans Dev List Subscribe" \
href="mailto:dev-subscribe@xmlbeans.apache.org"/>
<mailunsubdev label="XmlBeans Dev List UnSubscribe" \
href="mailto:dev-unsubscribe@xmlbeans.apache.org"/>
<mailsubcvs label="XmlBeans CVS List Subscribe" \
href="mailto:commits-subscribe@xmlbeans.apache.org"/>
<mailunsubcvs label="XmlBeans CVS List UnSubscribe" \
href="mailto:commits-unsubscribe@xmlbeans.apache.org"/>
<userlistarchive label="XmlBeams User List Archive" \
href="http://issues.apache.org/eyebrowse/SummarizeList?listId=277"/>
<devlistarchive label="XmlBeans Dev List Archive" \
href="http://issues.apache.org/eyebrowse/SummarizeList?listId=278"/>
<cvslistarchive label="XmlBeans CVS List Archive" \
href="http://issues.apache.org/eyebrowse/SummarizeList?listId=276"/> \
</external-refs> </site>
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@xmlbeans.apache.org
For additional commands, e-mail: dev-help@xmlbeans.apache.org
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic