blob: 97bbeaf9dffd5b678a53a8193a9e108c73347ec8 [file] [log] [blame]
/* Copyright 2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.xmlbeans;
import org.apache.xmlbeans.impl.schema.XmlObjectFactory;
import org.w3c.dom.Node;
import javax.xml.namespace.QName;
/**
* Corresponds to the XML Schema
* <a target="_blank" href="http://www.w3.org/TR/xmlschema-1/#key-urType">xs:anyType</a>,
* the base type for all XML Beans.
* <p>
* Since all XML Schema types are translated into corresponding XML Bean
* classes, and all Schema type derivation corresponds to Java class
* inheritance, the fact that all Schema types derive from xs:anyType means
* that all XML Bean classes derive from XmlObject.
* <p>
* On this base class you will find a number of common facilities that
* all XML Bean classes provide:
* <p>
* <ul>
* <li>Every XML Bean class has an inner Factory class for creating and parsing
* instances, including XmlObject. Use {@link XmlObjectFactory} itself
* to produce untyped XML trees or XML trees that implement specific
* subtypes of XmlObject depending on a recognized root document element.
* If you depend on the automatic type inference, you will want to understand
* the type inference issues described below.
* <li>To write out an accurate XML file for the XML tree under this
* XmlObject, use one of the {@link #save} methods,
* or {@link #newInputStream} or {@link #newReader}.
* Use {@link #toString} to produce a pretty-printed representation of the
* XML subtree under this XML Object. If you save interior portions of
* an XML document, you will want to understand the inner contents
* versus outer container issues described below.
* <li>It is also simple to copy an XmlObject instance to or from a standard
* DOM tree or SAX stream. Use {@link XmlObjectFactory#parse(Node)},
* for example, to load from DOM; use {@link XmlObjectFactory#newXmlSaxHandler}
* to load from SAX; use {@link #newDomNode()} to save to DOM; and use
* {@link #save(org.xml.sax.ContentHandler, org.xml.sax.ext.LexicalHandler)}
* to save to SAX.
* <li>Use {@link #validate} to validate the subtree of XML under this
* XML Object. If you wish to get information about the location
* and reason for validation errors, see {@link XmlOptions#setErrorListener},
* and use {@link #validate(XmlOptions)}.
* <li>Use {@link #newCursor} to access the full XML infoset, for example,
* if you need to determine interleaved element order or manipulate
* annotations, comments, or mixed content. You can get an element name with
* a cursor by calling {@link XmlCursor#getName() cursor.getName()} when the
* cursor is positioned at an element's START token. See {@link XmlCursor}.
* <li>Use {@link #selectPath} to find other XmlObjects in the subtree underneath
* this XmlObject using relative XPaths. (In selectPath, "." indicates
* the current element or attribute.)
* </ul>
* <p>
* Type inference. When using {@link XmlObjectFactory} to parse XML documents,
* the actual document type is not {@link XmlObject#type} itself, but a subtype
* based on the contents of the parsed document. If the parsed document
* contains a recognized root document element, then the actual type of the
* loaded instance will be the matching Document type. For example:
* <pre>
* XmlObject xobj = XmlObject.Factory.parse(myDocument);
* if (xobj instanceof MyOrderDocument) // starts w/ &lt;my-order&gt;
* {
* MyOrderDocument mydoc = (MyOrderDocument)xobj;
* if (!xobj.validate())
* System.out.println("Not a valid my-order document");
* }
* else
* {
* System.out.println("Not a my-order document");
* }
* </pre>
* Every XML Bean class has its own inner Factory class,
* so if you actually know exactly which XML Bean document type
* you want to load as in the example above, you should use the
* the specific XML Bean Factory class instead. For example:
* <pre>
* MyOrderDocument mydoc = MyOrderDocument.Factory.parse(myDocument);
* </pre>
* The code above will throw an exception if the parsed document
* does not begin with the proper (my-order) element.
* <p>
* Inner versus outer. An XmlObject represents the
* <em>contents</em> of an element or attribute, <em>not</em> the element
* or attribute itself. So when you validate or save an XmlObject, you
* are validating or saving its contents, not its container. For example,
* if the XmlObject represents the contents of an element which happens
* to itself be in the wrong order relative to its siblings, validate will
* not complain about the misplacement of the element itself. On the other hand, if
* elements <em>within</em> the XmlObject are in the wrong order, validate
* will complain. Similarly, when saving the contents of an interior
* XmlObject, it is the contents of an element, not the element itself,
* which is saved by default.
* <p>
* Reading and writing fragments. When reading or writing the contents of a
* whole XML document, the standard XML representation for a document is used.
* However, there is no standard concrete XML representation for "just the
* contents" of an interior element or attribute. So when one is needed,
* the tag &lt;xml-fragment&gt; is used to wrap the contents. This tag is used
* can also be used to load just the contents for an XmlObject document fragment
* of arbitrary type. If you wish to save out the XmlObject's container element
* along with its contents, use {@link XmlOptions#setSaveOuter}.
* <p>
* Implementing XmlObject. The XMLBeans library does not support arbitrary
* implementations of XmlObject - in almost all cases, you should only use
* the implementations of XmlObject provided by the XMLBeans compiler itself.
* If you need to implement XmlObject yourself, you should subclass
* FilterXmlObject in order to delegate to another underlying XmlObject
* implementation. This technique will allow you to use your code unchanged
* with future versions of XMLBeans that add additional methods on XmlObject.
*/
public interface XmlObject extends XmlTokenSource {
XmlObjectFactory<XmlObject> Factory = new XmlObjectFactory<>("_BI_anyType");
/**
* The constant {@link SchemaType} object representing this schema type.
*/
SchemaType type = Factory.getType();
/**
* @return The schema type for this instance. This is a permanent,
* unchanging property of the instance.
*/
SchemaType schemaType();
/**
* Does a deep validation of the entire subtree under the
* object, but does not validate the parents or siblings
* of the object if the object is in the interior of an xml
* tree.
*
* @return true if the contents of this object are valid
* according to schemaType().
*/
boolean validate();
/**
* <p>Just like validate(), but with options.</p>
* <p>If you wish to collect error messages and locations while validating,
* use the {@link XmlOptions#setErrorListener} method. With that method,
* you can specify an object in which to store messages related to validation.
* The following is a simple example.</p>
*
* <pre>
* // Create an XmlOptions instance and set the error listener.
* XmlOptions validateOptions = new XmlOptions();
* ArrayList errorList = new ArrayList();
* validateOptions.setErrorListener(errorList);
*
* // Validate the XML.
* boolean isValid = newEmp.validate(validateOptions);
*
* // If the XML isn't valid, loop through the listener's contents,
* // printing contained messages.
* if (!isValid)
* {
* for (int i = 0; i &lt; errorList.size(); i++)
* {
* XmlError error = (XmlError)errorList.get(i);
*
* System.out.println("\n");
* System.out.println("Message: " + error.getMessage() + "\n");
* System.out.println("Location of invalid XML: " +
* error.getCursorLocation().xmlText() + "\n");
* }
* }
* </pre>
*
* @param options An object that implements the {@link java.util.Collection
* Collection} interface.
* @return true if the contents of this object are valid
* according to schemaType().
*/
boolean validate(XmlOptions options);
/**
* Selects a path. Path can be a string or precompiled path String.
* <p>
* <p>
* The path must be a relative path, where "." represents the
* element or attribute containing this XmlObject, and it must select
* only other elements or attributes. If a non-element or non-attribute
* is selected, an unchecked exception is thrown.
* <p>
* <p>
* The array that is returned contains all the selected
* XmlObjects, within the same document, listed in document
* order. The actual array type of the result is inferred
* from the closest common base type of selected results.
* <p>
* <p>
* Here is an example of usage. Suppose we have a global
* element definition for "owner" whose type is "person":
*
* <pre>
* &lt;schema targetNamespace="http://openuri.org/sample"&gt;
* &lt;element name="owner" type="person"/&gt;
* &lt;complexType name="person"&gt;
* [...]
* &lt;/complexType&gt;
* &lt;/schema&gt;
* </pre>
* <p>
* and suppose "owner" tags can be scattered throughout the
* document. Then we can write the following code to find
* them all:
*
* <pre>
* import org.openuri.sample.Person;
* import org.apache.xmlbeans.*;
* [...]
* XmlObject xobj = XmlObject.Factory.parse(myFile);
* Person[] results;
* results = (Person[])xobj.selectPath(
* "declare namespace s='http://www.openuri.org/sample' " +
* ".//s:owner");
* </pre>
* <p>
* Notice the way in which namespace declarations are done in XPath 2.0.
* Since XPath can only navigate within an XML document - it cannot
* construct new XML - the resulting XmlObjects all reside in
* the same XML document as this XmlObject itself.
*
* @param path the xpath
* @return an array of all selected XmlObjects
*/
XmlObject[] selectPath(String path);
/**
* Selects a path, applying options.
*
* @param path the xpath
* @param options the options used to execute the xpath
* @return an array of all selected XmlObjects
* @see #selectPath(String)
*/
XmlObject[] selectPath(String path, XmlOptions options);
/**
* Executes a query. Query can be a string or precompiled query String.
* <p>
* An XQuery is very similar to an XPath, except that it also permits
* construction of new XML. As a result, the XmlObjects that are
* returned from execQuery are in newly created documents, separate
* from the XmlObject on which the query is executed.
* <p>
* Syntax and usage is otherwise similar to selectPath.
* <p>
*
* @param query The XQuery expression
* @return an array of all selected XmlObjects
* @see #selectPath(String)
*/
XmlObject[] execQuery(String query);
/**
* Executes a query with options.
* <p>
* Use the <em>options</em> parameter to specify the following:</p>
*
* <table>
* <tr><th>To specify this</th><th>Use this method</th></tr>
* <tr>
* <td>The document type for the root element.</td>
* <td>{@link XmlOptions#setDocumentType}</td>
* </tr>
* <tr>
* <td>To replace the document element with the specified QName when constructing the
* resulting document.</td>
* <td>{@link XmlOptions#setLoadReplaceDocumentElement}</td>
* </tr>
* <tr>
* <td>To strip all insignificant whitespace when constructing a document.</td>
* <td>{@link XmlOptions#setLoadStripWhitespace}</td>
* </tr>
* <tr>
* <td>To strip all comments when constructing a document.</td>
* <td>{@link XmlOptions#setLoadStripComments}</td>
* </tr>
* <tr>
* <td>To strip all processing instructions when constructing a document.</td>
* <td>{@link XmlOptions#setLoadStripProcinsts}</td>
* </tr>
* <tr>
* <td>A map of namespace URI substitutions to use when constructing a document.</td>
* <td>{@link XmlOptions#setLoadSubstituteNamespaces}</td>
* </tr>
* <tr>
* <td>Additional namespace mappings to be added when constructing a document.</td>
* <td>{@link XmlOptions#setLoadAdditionalNamespaces}</td>
* </tr>
* <tr>
* <td>To trim the underlying XML text buffer immediately after constructing
* a document, resulting in a smaller memory footprint.</td>
* <td>{@link XmlOptions#setLoadTrimTextBuffer}</td>
* </tr>
* <tr>
* <td>Whether value facets should be checked as they are set.</td>
* <td>{@link XmlOptions#setValidateOnSet}</td>
* </tr>
* </table>
*
* @param query The XQuery expression.
* @param options Options as described.
* @return an array of all selected XmlObjects
* @see #execQuery(String)
*/
XmlObject[] execQuery(String query, XmlOptions options);
/**
* Changes the schema type associated with this data and
* returns a new XmlObject instance whose schemaType is the
* new type.
* <p>
* Returns the new XmlObject if the type change was successful,
* the old XmlObject if no changes could be made. <p/>
* Certain type changes may be prohibited in the interior of an xml
* tree due to schema type system constraints (that is, due
* to a parent container within which the newly specified
* type is not permissible), but there are no constraints
* at the roottype changes are never
* prohibited at the root of an xml tree.
* <p>
* If the type change is allowed, then the new XmlObject should
* be used rather than the old one. The old XmlObject instance and
* any other XmlObject instances in the subtree are permanently
* invalidated and should not be used. (They will return
* XmlValueDisconnectedException if you try to use them.)
* <p>
* If a type change is done on the interior of an Xml
* tree, then xsi:type attributes are updated as needed.
*
* @return a new XmlObject instance whose schemaType is the new type
*/
XmlObject changeType(SchemaType newType);
/**
* Changes the schema type associated with this data using substitution
* groups and returns an XmlObject instance whose schemaType is the
* new type and container name is the new name.
* <p>
* Returns the new XmlObject if the substitution was successful,
* the old XmlObject if no changes could be made. <p/>
* In order for the operation to succeed, several conditions must hold:
* <ul><li> the container of this type must be an element </li>
* <li> a global element with the name <code>newName</code> must exist
* and must be in the substitution group of the containing element </li>
* <li> the <code>newType</code> type must be consistent with the declared
* type of the new element </li></ul>
* <p>
* If the type change is allowed, then the new XmlObject should
* be used rather than the old one. The old XmlObject instance and
* any other XmlObject instances in the subtree are permanently
* invalidated and should not be used. (They will return
* XmlValueDisconnectedException if you try to use them.)
* If necessary, xsi:type attributes are updated.
*
* @param newName the new name
* @param newType the new type
* @return an XmlObject instance whose schemaType is the
* new type and container name is the new name
*/
XmlObject substitute(QName newName, SchemaType newType);
/**
* Note that in order to be nil,
* the value must be in an element, and the element containing
* the value must be marked as nillable in the schema.
*
* @return true if the value is nil.
*/
boolean isNil();
/**
* Sets the value to nil. The element containing the value must
* be marked as nillable in the schema.
*/
void setNil();
/**
* The string is pretty-printed. If you want a non-pretty-printed
* string, or if you want to control options precisely, use the
* xmlText() methods.
* <p>
* Note that when producing XML any object other than very root of the
* document, then you are guaranteed to be looking at only a fragment
* of XML, i.e., just the contents of an element or attribute, and
* and we will produce a string that starts with an <code>&lt;xml-fragment&gt;</code> tag.
* The XmlOptions.setSaveOuter() option on xmlText can be used to produce
* the actual element name above the object if you wish.
*
* @return a XML string for this XML object.
*/
String toString();
/**
* Immutable values do not have a position in a tree; rather, they are
* stand-alone simple type values. If the object is immutable, the equals()
* methods tests for value equality, and the object can be used as the key for a hash.
*
* @return true if the value is an immutable value.
*/
boolean isImmutable();
/**
* Set the value/type of this XmlObject to be a copy of the source
* XmlObject. Because the type of the source may be different than this
* target, this XmlObject may become defunct. In this case the new
* XmlObject is returned. If no type change happens, the same this will be
* returned.
*/
XmlObject set(XmlObject srcObj);
/**
* Returns a deep copy of this XmlObject. The returned object has the
* same type as the current object, and has all the content of
* the XML document underneath the current object. Note that
* any parts of the XML document above or outside this XmlObject are
* not copied.
* <p>
* Note: The result object will be in the same synchronization domain as the source,
* and additional synchronization is required for concurrent access.
* To use a different synchronization domain use setCopyUseNewSynchronizationDomain
* option with copy(XmlOptions) method.
*
* @see #copy(XmlOptions)
* @see org.apache.xmlbeans.XmlOptions#setCopyUseNewSynchronizationDomain(boolean)
*/
XmlObject copy();
/**
* Returns a deep copy of this XmlObject. The returned object has the
* same type as the current object, and has all the content of
* the XML document underneath the current object. Note that
* any parts of the XML document above or outside this XmlObject are
* not copied.
* <p>
* Note: The result object will be in the same synchronization domain as the source,
* and additional synchronization is required for concurrent access.
* To use a different synchronization domain use setCopyUseNewSynchronizationDomain
* option when creating the original XmlObject.
*
* @see org.apache.xmlbeans.XmlOptions#setCopyUseNewSynchronizationDomain(boolean)
*/
XmlObject copy(XmlOptions options);
/**
* True if the xml values are equal. Two different objects
* (which are distinguished by equals(obj) == false) may of
* course have equal values (valueEquals(obj) == true).
* <p>
* Usually this method can be treated as an ordinary equivalence
* relation, but actually it is not is not transitive.
* Here is a precise specification:
* <p>
* There are two categories of XML object: objects with a known
* instance type, and objects whose only known type is one of the
* ur-types (either AnyType or AnySimpleType). The first category
* is compared in terms of logical value spaces, and the second
* category is compared lexically.
* <p>
* Within each of these two categories, valueEquals is a well-behaved
* equivalence relation. However, when comparing an object of known
* type with an object with ur-type, the comparison is done by attempting
* to convert the lexical form of the ur-typed object into the other
* type, and then comparing the results. Ur-typed objects are therefore
* treated as lexical wildcards and may be equal to objects in different
* value spaces, even though the objects in different value spaces are
* not equal to each other.
* <p>
* For example, the anySimpleType value "1" will compare as an
* equalValue to the string "1", the float value "1.0", the double
* value "1.0", the decimal "1", and the GYear "1", even though
* all these objects will compare unequal to each other since they
* lie in different value spaces.
* Note: as of XMLBeans 2.2.1 only implemented for simple type values.
*/
boolean valueEquals(XmlObject obj);
int valueHashCode();
/**
* Implements the Comparable interface by comparing two simple
* xml values based on their standard XML schema ordering.
* Throws a ClassCastException if no standard ordering applies,
* or if the two values are incomparable within a partial order.
*/
int compareTo(Object obj);
/**
* This comparison method is similar to compareTo, but rather
* than throwing a ClassCastException when two values are incomparable,
* it returns the number 2. The result codes are -1 if this object
* is less than obj, 1 if this object is greater than obj, zero if
* the objects are equal, and 2 if the objects are incomparable.
*/
int compareValue(XmlObject obj);
/**
* LESS_THAN is -1. See {@link #compareValue}.
*/
int LESS_THAN = -1;
/**
* EQUAL is 0. See {@link #compareValue}.
*/
int EQUAL = 0;
/**
* GREATER_THAN is 1. See {@link #compareValue}.
*/
int GREATER_THAN = 1;
/**
* NOT_EQUAL is 2. See {@link #compareValue}.
*/
int NOT_EQUAL = 2;
/**
* Selects the contents of the children elements with the given name.
*
* @param elementName The name of the elements to be selected.
* @return Returns the contents of the selected elements.
*/
XmlObject[] selectChildren(QName elementName);
/**
* Selects the contents of the children elements with the given name.
*
* @param elementUri The URI of the elements to be selected.
* @param elementLocalName The local name of the elements to be selected.
* @return Returns the contents of the selected elements.
*/
XmlObject[] selectChildren(String elementUri, String elementLocalName);
/**
* Selects the contents of the children elements that are contained in the elementNameSet.
*
* @param elementNameSet Set of element names to be selected.
* @return Returns the contents of the selected elements.
* @see SchemaType#qnameSetForWildcardElements()
* @see QNameSetBuilder for creating sets of qnames
*/
XmlObject[] selectChildren(QNameSet elementNameSet);
/**
* Selects the content of the attribute with the given name.
*
* @param attributeName The name of the attribute to be selected.
* @return Returns the contents of the selected attribute.
*/
XmlObject selectAttribute(QName attributeName);
/**
* Selects the content of the attribute with the given name.
*
* @param attributeUri The URI of the attribute to be selected.
* @param attributeLocalName The local name of the attribute to be selected.
* @return Returns the content of the selected attribute.
*/
XmlObject selectAttribute(String attributeUri, String attributeLocalName);
/**
* Selects the contents of the attributes that are contained in the elementNameSet.
*
* @param attributeNameSet Set of attribute names to be selected.
* @return Returns the contents of the selected attributes.
* @see SchemaType#qnameSetForWildcardAttributes()
* @see QNameSetBuilder for creating sets of qnames
*/
XmlObject[] selectAttributes(QNameSet attributeNameSet);
}