[prev in list] [next in list] [prev in thread] [next in thread]
List: xmlbeans-dev
Subject: Tutorial image href fix
From: "Steven Traut" <straut () bea ! com>
Date: 2004-10-29 17:40:24
Message-ID: 4C2F1577F2EF2840A9AE9EC61860C88199664A () usseex01 ! amer ! bea ! com
[Download RAW message or body]
I noticed this morning that the tutorial I contributed a while back puts the images \
in the wrong place after the Forrest build (my bad -- seems Forrest uses the href \
value as a destination when copying things around during build). So they don't show \
up on the page after the site has been posted to the server. This fixes the problem \
by using hrefs that have the images copied to the images folder where the others are.
<<tutorial_getstarted.xml>>
Steve
["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
the three technologies that make up version 1 of XMLBeans: \
strongly-typed access to
XML through compiled schema, 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 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>Each of the four child elements has its 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>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>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 POUpdater \
instances/easypo/easypo.xml "a new item" 5.0 20.00 \
6</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>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>
---------------------------------------------------------------------
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