All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.axiom.om.OMElement Maven / Gradle / Ivy

There is a newer version: 1.4.0
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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.axiom.om;

import javax.xml.namespace.NamespaceContext;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

import org.apache.axiom.om.util.StAXParserConfiguration;
import org.apache.axiom.om.xpath.AXIOMXPath;

import java.io.IOException;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.util.Iterator;

/**
 * A particular kind of node that represents an element infoset information item.
 * 

* An element has a collection of children, attributes, and namespace declarations. In contrast with * DOM, this interface exposes namespace declarations separately from the attributes. *

* Namespace declarations are either added explicitly using * {@link #declareNamespace(String, String)}, {@link #declareDefaultNamespace(String)} or * {@link #declareNamespace(OMNamespace)}, or are created implicitly as side effect of other method * calls: *

    *
  • If the element is created with a namespace and no matching namespace declaration is in scope * in the location in the tree where the element is created, then an appropriate namespace * declaration will be automatically added to the newly created element. The exact rules depend on * the method chosen to create the element; see for example {@link OMFactory#createOMElement(QName)}. *
  • If an attribute with a namespace is added, but no matching namespace declaration is in scope * in the element, one is automatically added. See {@link #addAttribute(OMAttribute)} for more * details. *
* Thus, creating a new element or adding an attribute preserves the consistency of the object model * with respect to namespaces. However, Axiom does not enforce namespace well-formedness for all * possible operations on the object model. E.g. moving an element from one location in the tree to * another one may cause the object model to loose its namespace well-formedness. In that case it is * possible that the object model contains elements or attributes with namespaces for which no * corresponding namespace declarations are in scope. *

* Fortunately, loosing namespace well-formedness has only very limited impact: *

    *
  • If namespace well-formedness is lost, the string to {@link QName} resolution for attribute * values and element content may be inconsistent, i.e. {@link #resolveQName(String)}, * {@link #getTextAsQName()} and {@link OMText#getTextAsQName()} may return incorrect results. * However, it should be noted that these methods are most relevant for object model instances that * have been loaded from existing documents or messages. These object models are guaranteed to be * well-formed with respect to namespaces (unless they have been modified after loading). *
  • During serialization, Axiom will automatically repair any namespace inconsistencies. It will * add necessary namespace declarations to the output document where they are missing in the object * model and generate modified namespace declarations where the original ones in the object model * are inconsistent. It will also omit redundant namespace declarations. Axiom guarantees that in * the output document, every element and attribute (and {@link OMText} instance with a * {@link QName} value) will have the same namespace URI as in the object model, thus preserving the * intended semantics of the document. On the other hand, the namespace prefixes used in the output * document may differ from the ones in the object model. *
  • More precisely, Axiom will always make sure that any {@link OMElement} or {@link OMAttribute} * node will keep the namespace URI that has been assigned to the node at creation time, unless the * namespace is explicitly changed using {@link #setNamespace(OMNamespace)} or * {@link OMAttribute#setOMNamespace(OMNamespace)}. *
*/ public interface OMElement extends OMNode, OMContainer, OMNamedInformationItem { /** * Returns a filtered list of children - just the elements. * * @return Returns an iterator over the child elements. * @see #getChildren() * @see #getChildrenWithName(javax.xml.namespace.QName) */ Iterator getChildElements(); /** * Add a namespace declaration for the given namespace URI to this element, optionally * generating a prefix for that namespace. *

* Note that this method can't be used to declare a default namespace. For that purpose use * {@link #declareDefaultNamespace(String)} or {@link #declareNamespace(OMNamespace)}. * * @param uri * The namespace to declare in the current scope. The caller is expected to ensure * that the URI is a valid namespace name. * @param prefix * The prefix to associate with the given namespace. The caller is expected to ensure * that this is a valid XML prefix. If null or the empty string is * given, a prefix will be auto-generated. Please note that using the empty string * for this purpose is deprecated and will no longer be supported in Axiom 1.3. * @return the created namespace information item * @throws IllegalArgumentException * if an attempt is made to bind a prefix to the empty namespace name * @see #declareNamespace(OMNamespace) * @see #findNamespace(String, String) * @see #getAllDeclaredNamespaces() */ OMNamespace declareNamespace(String uri, String prefix); /** * Add a namespace declaration for the default namespace to this element. *

* Note that this method will never change the namespace of the element itself. If an attempt is * made to add a namespace declaration that conflicts with the namespace information of the * element, an exception is thrown. * * @param uri * The default namespace to declare in the current scope. The caller is expected to * ensure that the URI is a valid namespace name. * @return the created namespace information item * @throws OMException * if an attempt is made to add a conflicting namespace declaration */ OMNamespace declareDefaultNamespace(String uri); /** * Get the default namespace in scope on this element. * * @return The default namespace or null if no default namespace is in scope. This * method never returns an {@link OMNamespace} object with an empty namespace URI; if * the element or one of its ancestors has a xmlns="" declaration, then * null is returned. Note that if the method returns an {@link OMNamespace} * object, then its prefix will obviously be the empty string. */ OMNamespace getDefaultNamespace(); /** * Declares a namespace with the element as its scope. * * @param namespace * The namespace to declare. If the prefix specified by the {@link OMNamespace} * object is null, then a prefix will be generated. * @return The declared namespace, which will be equal to the {@link OMNamespace} object passed * as parameter, except if the prefix was null, in which case the return * value contains the generated prefix. * @throws IllegalArgumentException * if an attempt is made to bind a prefix to the empty namespace name * @see #declareNamespace(String, String) * @see #findNamespace(String, String) * @see #getAllDeclaredNamespaces() */ OMNamespace declareNamespace(OMNamespace namespace); /** * Add a namespace declaration that undeclares a given prefix. Prefix undeclaring is supported * in XML 1.1, but forbidden in XML 1.0. If an object model on which this method has been used * is later serialized to an XML 1.0 document, an error will occur. When serialized to an XML * 1.1 document, a namespace declaration in the form xmlns:p="" will be produced. *

* A namespace declaration with empty namespace name will be added even if no existing namespace * declaration for the given prefix is in scope in the context of the current element. If a * namespace declaration for the given prefix is already defined on this element, it will be * replaced. *

* The namespace declaration created by this method will be returned by * {@link #getAllDeclaredNamespaces()}. It is represented as an {@link OMNamespace} object for * which {@link OMNamespace#getNamespaceURI()} returns an empty string. * * @param prefix * the prefix to undeclare */ void undeclarePrefix(String prefix); /** * Finds a namespace with the given uri and prefix, in the scope of the hierarchy. *

*

Searches from the current element and goes up the hiararchy until a match is found. If no * match is found, returns null.

*

*

Either prefix or uri should be null. Results are undefined if both are * specified.

* * @param uri The namespace to look for. If this is specified, prefix should be * null. * @param prefix The prefix to look for. If this is specified, uri should be null. * @return Returns the matching namespace declaration, or null if none was found. * @see #declareNamespace(String, String) * @see #declareNamespace(OMNamespace) * @see #getAllDeclaredNamespaces() */ OMNamespace findNamespace(String uri, String prefix); /** * Checks for a namespace in the context of this element with the given prefix and returns the * relevant namespace object, if available. If not available, returns null. * * @param prefix */ // TODO: specify if null is a valid argument // TODO: specify the return value if prefix is the empty string and there is no default namespace // (should we return null or an OMNamespace instance with namespaceURI and prefix set to ""?) OMNamespace findNamespaceURI(String prefix); /** * Returns an iterator for all of the namespaces declared on this element. Note that this is not * the same as the set of namespace declarations in scope. Since building a namespace context * and resolving namespace prefixes has some subtleties associated with it (such as masked * namespace declarations and prefix undeclaring), it is generally recommended to use one of the * following specialized methods for this purpose: *
    *
  • {@link #getNamespacesInScope()} or {@link #getNamespaceContext(boolean)} to calculate the * namespace context for the element. *
  • {@link #findNamespace(String, String)} and {@link #findNamespaceURI(String)} to resolve a * namespace prefix or to find a namespace prefix for a given URI. *
  • {@link #resolveQName(String)} to resolve a QName literal. *
  • {@link AXIOMXPath#AXIOMXPath(OMElement, String)} or * {@link AXIOMXPath#AXIOMXPath(OMAttribute)} to create an XPath expression using the namespace * context of a given element. *
*

* It is expected that applications only rarely use {@link #getAllDeclaredNamespaces()} * directly. *

* The iterator returned by this method supports {@link Iterator#remove()} and that method can * be used to remove a namespace declaration from this element. * * @return An iterator over the {@link OMNamespace} items declared on this element. Note that * the iterator may be invalidated by a call to {@link #declareNamespace(OMNamespace)}, * {@link #declareNamespace(String, String)}, {@link #declareDefaultNamespace(String)} * or any other method that modifies the namespace declarations of this element. */ Iterator getAllDeclaredNamespaces() throws OMException; /** * Get an iterator that returns all namespaces in scope for this element. This method may be * used to determine the namespace context for this element. For any given prefix, the iterator * returns at most one {@link OMNamespace} object with that prefix, and this object specifies * the namespace URI bound to the prefix. The iterator returns an {@link OMNamespace} object * with an empty prefix if and only if there is a default namespace. It will never return an * {@link OMNamespace} object with both the prefix and the namespace URI set to the empty * string, even if the element or one of its ancestors has a namespace declaration of the form * xmlns="". *

* The order in which the iterator returns the namespaces is undefined, and invoking the * {@link Iterator#remove()} method on the returned iterator is not supported. The iterator may * be a "live" object, which means that results are undefined if the document is modified (in a * way that would modify the namespace context for the element) while the iterator is in use. * * @return an iterator over all namespaces in scope for this element */ Iterator getNamespacesInScope(); /** * Get the namespace context of this element, as determined by the namespace declarations * present on this element and its ancestors. *

* The method supports two different {@link NamespaceContext} implementation variants: *

    *
  • A "live" variant that keeps a reference to the element and that performs lookups by * accessing the object model. This means that any change in the object model will automatically * be reflected by the {@link NamespaceContext}. *
  • A "detached" variant that stores a snapshot of the namespace context and that doesn't * have any reference to the object model. *
*

* Typically, creating a live {@link NamespaceContext} is cheaper, but the lookup performance of * a detached {@link NamespaceContext} is better. The detached variant should always be used if * the reference to the {@link NamespaceContext} is kept longer than the object model itself, * because in this case a live {@link NamespaceContext} would prevent the object model from * being garbage collected. * * @param detached * true if the method should return a detached implementation, * false if the method should return a live object * @return The namespace context for this element. Note that the caller must not make any * assumption about the actual implementation class returned by this method. */ NamespaceContext getNamespaceContext(boolean detached); /** * Returns a list of OMAttributes. *

*

Note that the iterator returned by this function will be invalidated by any * addAttribute call.

* * @return Returns an {@link Iterator} of {@link OMAttribute} items associated with the * element. * @see #getAttribute * @see #addAttribute(OMAttribute) * @see #addAttribute(String, String, OMNamespace) */ Iterator getAllAttributes(); /** * Returns a named attribute if present. * * @param qname the qualified name to search for * @return Returns an OMAttribute with the given name if found, or null */ OMAttribute getAttribute(QName qname); /** * Returns a named attribute's value, if present. * * @param qname * the qualified name to search for * @return The attribute value, or null if no matching attribute is found. */ String getAttributeValue(QName qname); /** * Adds an attribute to this element. *

* If the attribute already has an owner, the attribute is cloned (i.e. its name, value and * namespace are copied to a new attribute) and the new attribute is added to the element. * Otherwise the existing instance specified by the attr parameter is added to * the element. In both cases the owner of the added attribute is set to be the particular * OMElement. *

* If there is already an attribute with the same name and namespace URI, it will be replaced * and its owner set to null. *

* In the particular case where the attribute specified by attr is already owned * by the element, calling this method has no effect. *

* Attributes are not stored in any particular order. In particular, there is no guarantee * that the added attribute will be returned as the last item by the iterator produced by * a subsequent call to {@link #getAllAttributes()}. *

* If the attribute being added has a namespace, but no corresponding namespace declaration is * in scope for the element (i.e. declared on the element or one of its ancestors), a new * namespace declaration is added to the element. Note that both the namespace prefix and URI * are taken into account when looking for an existing namespace declaration. * * @param attr The attribute to add. * @return The attribute that was added to the element. As described above this may or may * not be the same as attr, depending on whether the attribute specified * by this parameter already has an owner or not. */ OMAttribute addAttribute(OMAttribute attr); /** * Adds an attribute to this element. *

* If the element already has an attribute with the same local name and namespace URI, then this * existing attribute will be removed from the element, i.e. this method will always create a * new {@link OMAttribute} instance and never update an existing one. * * @param localName * The local name for the attribute. * @param value * The string value of the attribute. This function does not check to make sure that * the given attribute value can be serialized directly as an XML value. The caller * may, for example, pass a string with the character 0x01. * @param ns * The namespace has to be one of the in scope namespace. i.e. the passed namespace * must be declared in the parent element of this attribute or ancestors of the * parent element of the attribute. * @return Returns the added attribute. * @throws IllegalArgumentException * if an attempt is made to create a prefixed attribute with an empty namespace name */ OMAttribute addAttribute(String localName, String value, OMNamespace ns); /** * Method removeAttribute * * @param attr */ void removeAttribute(OMAttribute attr); /** * Method setBuilder. * * @param wrapper */ void setBuilder(OMXMLParserWrapper wrapper); /** * Returns the first child element of the element. * * @return Returns the first child element of the element, or null if none was found. */ OMElement getFirstElement(); /** * Set the content of this element to the given text. If the element has children, then all * these children are detached before the content is set. If the parameter is a non empty * string, then the element will have a single child of type {@link OMText} after the method * returns. If the parameter is null or an empty string, then the element will have * no children. * * @param text * the new text content for the element */ void setText(String text); /** * Set the content of this element to the given {@link QName}. If no matching namespace * declaration for the {@link QName} is in scope, then this method will add one. If the * {@link QName} specifies a namespace URI but no prefix, then a prefix will be generated. If * the element has children, then all these children are detached before the content is set. If * the parameter is not null, then the element will have a single child of type * {@link OMText} after the method returns. If the parameter is null, then the * element will have no children. * * @param qname * the QName value */ void setText(QName qname); /** * Returns the non-empty text children as a string. *

* This method iterates over all the text children of the element and concatenates * them to a single string. Only direct children will be considered, i.e. the text * is not extracted recursively. For example the return value for * <element>A<child>B</child>C</element> will be AC. *

* All whitespace will be preserved. * * @return A string representing the concatenation of the child text nodes. * If there are no child text nodes, an empty string is returned. */ String getText(); /** * Returns a stream representing the concatenation of the text nodes that are children of a * this element. The stream returned by this method produces exactly the same character * sequence as the the stream created by the following expression: *

new StringReader(element.getText())
*

* The difference is that the stream implementation returned by this method is optimized for * performance and is guaranteed to have constant memory usage, provided that: *

    *
  1. The method is not required to cache the content of the {@link OMElement}, i.e. * cache is false or the element is an {@link OMSourcedElement} that * is backed by a non destructive {@link OMDataSource}. *
  2. The underlying parser (or the implementation of the underlying {@link XMLStreamReader} in * the case of an {@link OMSourcedElement}) is non coalescing. Note that this is not the default * in Axiom and it may be necessary to configure the parser with * {@link StAXParserConfiguration#NON_COALESCING}. *
* * @param cache * whether to enable caching when accessing the element * @return a stream representing the concatenation of the text nodes * * @see #getText() */ Reader getTextAsStream(boolean cache); /** * Write the content of the text nodes that are children of a given element to a {@link Writer}. * If cache is true, this method has the same effect as the following instruction: *
out.write(element.getText())
*

* The difference is that this method is guaranteed to have constant memory usage and is * optimized for performance (with the same restrictions that apply to * {@link #getTextAsStream(boolean)}). *

* The method does not call {@link Writer#close()}. * * @param out * the stream to write the content to * @param cache * whether to enable caching when accessing the element * @throws OMException * if an error occurs when reading from the element * @throws IOException * if an error occurs when writing to the stream * * @see #getText() */ void writeTextTo(Writer out, boolean cache) throws IOException; /** * Resolve the content of this element to a {@link QName}. The QName is interpreted in a way * that is compatible with the XML schema specification. In particular, surrounding whitespace * is ignored. * * @return the resolved QName, or null if the element is empty or the QName could * not be resolved */ QName getTextAsQName(); /** * Set the namespace for this element. In addition to changing the namespace URI and prefix of * the element information item, this method ensures that a corresponding namespace declaration * exists. If no corresponding namespace declaration is already in scope, then a new one will be * added to this element. * * @param namespace * The new namespace for this element, or null to remove the namespace * from this element. If an {@link OMNamespace} instance with a null * prefix is given, then a prefix will be generated automatically. In this case, the * generated prefix can be determined using {@link #getNamespace()}. * @throws IllegalArgumentException * if an attempt is made to bind a prefix to the empty namespace name */ void setNamespace(OMNamespace namespace); /** * This will not search the namespace in the scope nor will declare in the current element, as * in setNamespace(OMNamespace). This will just assign the given namespace to the element. * * @param namespace */ void setNamespaceWithNoFindInCurrentScope(OMNamespace namespace); /** * Convenience method to serialize the element to a string with caching enabled. Caching means * that the object model tree for the element will be fully built in memory and can be accessed * after invoking this method. *

* This method produces the same result as {@link OMContainer#serialize(Writer)}. In particular, * the element is always serialized as plain XML and {@link OMText} nodes containing optimized * binary data are always inlined using base64 encoding. Since the output is accumulated into a * single string object, this may result in high memory consumption. Therefore this method * should be used with care. * * @return the serialized object model */ String toString(); /** * Convenience method to serialize the element to a string without caching. This method will not * built the object model tree in memory. This means that an attempt to access the object model * after invoking this method may result in an error (unless the object model was already fully * built before, e.g. because it was created programmatically). *

* As for {@link #toString()}, this method may cause high memory consumption for object model * trees containing optimized binary data and should therefore be used with care. * * @return the serialized object model */ String toStringWithConsume() throws XMLStreamException; /** * Resolves a QName literal in the namespace context defined by this element and produces a * corresponding {@link QName} object. The implementation uses the algorithm defined by the XML * Schema specification. In particular, the namespace for an unprefixed QName is the default * namespace (not the null namespace), i.e. QNames are resolved in the same way as element * names. * * @param qname * the QName literal to resolve * @return the {@link QName} object, or null if the QName can't be resolved, i.e. * if the prefix is not bound in the namespace context of this element */ QName resolveQName(String qname); /** * Clones this element. Since both elements are build compleletely, you will lose the differed * building capability. * * @return Returns OMElement. */ OMElement cloneOMElement(); void setLineNumber(int lineNumber); int getLineNumber(); /** * Serialize the node with caching enabled. *

* This method will always serialize the infoset as plain XML. In particular, any {@link OMText} * containing optimized binary will be inlined using base64 encoding. * * @param output * the byte stream to write the serialized infoset to * @throws XMLStreamException */ // Note: This method is inherited from both OMNode and OMContainer, but it is deprecated in // OMNode. We redeclare it here to make sure that people don't get a deprecation // warning when using the method on an OMElement. void serialize(OutputStream output) throws XMLStreamException; /** * Serialize the node with caching enabled. *

* This method will always serialize the infoset as plain XML. In particular, any {@link OMText} * containing optimized binary will be inlined using base64 encoding. * * @param writer * the character stream to write the serialized infoset to * @throws XMLStreamException */ // Note: This method is inherited from both OMNode and OMContainer, but it is deprecated in // OMNode. We redeclare it here to make sure that people don't get a deprecation // warning when using the method on an OMElement. void serialize(Writer writer) throws XMLStreamException; /** * Serialize the node with caching enabled. *

* The format of the output is controlled by the provided {@link OMOutputFormat} object. In * particular, {@link OMOutputFormat#setDoOptimize(boolean)} can be used to instruct this method * to produce an XOP/MTOM encoded MIME message. * * @param output * the byte stream to write the serialized infoset to * @param format * the output format to use * @throws XMLStreamException */ // Note: This method is inherited from both OMNode and OMContainer, but it is deprecated in // OMNode. We redeclare it here to make sure that people don't get a deprecation // warning when using the method on an OMElement. void serialize(OutputStream output, OMOutputFormat format) throws XMLStreamException; /** * Serialize the node with caching enabled. * * @param writer * the character stream to write the serialized infoset to * @param format * the output format to use * @throws XMLStreamException */ // Note: This method is inherited from both OMNode and OMContainer, but it is deprecated in // OMNode. We redeclare it here to make sure that people don't get a deprecation // warning when using the method on an OMElement. void serialize(Writer writer, OMOutputFormat format) throws XMLStreamException; /** * Serialize the node without caching. *

* This method will always serialize the infoset as plain XML. In particular, any {@link OMText} * containing optimized binary will be inlined using base64 encoding. * * @param output * the byte stream to write the serialized infoset to * @throws XMLStreamException */ // Note: This method is inherited from both OMNode and OMContainer, but it is deprecated in // OMNode. We redeclare it here to make sure that people don't get a deprecation // warning when using the method on an OMElement. void serializeAndConsume(OutputStream output) throws XMLStreamException; /** * Serialize the node without caching. *

* This method will always serialize the infoset as plain XML. In particular, any {@link OMText} * containing optimized binary will be inlined using base64 encoding. * * @param writer * the character stream to write the serialized infoset to * @throws XMLStreamException */ // Note: This method is inherited from both OMNode and OMContainer, but it is deprecated in // OMNode. We redeclare it here to make sure that people don't get a deprecation // warning when using the method on an OMElement. void serializeAndConsume(Writer writer) throws XMLStreamException; /** * Serialize the node without caching. *

* The format of the output is controlled by the provided {@link OMOutputFormat} object. In * particular, {@link OMOutputFormat#setDoOptimize(boolean)} can be used to instruct this method * to produce an XOP/MTOM encoded MIME message. * * @param output * the byte stream to write the serialized infoset to * @param format * the output format to use * @throws XMLStreamException */ // Note: This method is inherited from both OMNode and OMContainer, but it is deprecated in // OMNode. We redeclare it here to make sure that people don't get a deprecation // warning when using the method on an OMElement. void serializeAndConsume(OutputStream output, OMOutputFormat format) throws XMLStreamException; /** * Serialize the node without caching. * * @param writer * the character stream to write the serialized infoset to * @param format * the output format to use * @throws XMLStreamException */ // Note: This method is inherited from both OMNode and OMContainer, but it is deprecated in // OMNode. We redeclare it here to make sure that people don't get a deprecation // warning when using the method on an OMElement. void serializeAndConsume(Writer writer, OMOutputFormat format) throws XMLStreamException; }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy