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

es.rickyepoderi.wbxml.stream.WbXmlStreamWriter Maven / Gradle / Ivy

/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *    
 * Linking this library statically or dynamically with other modules 
 * is making a combined work based on this library. Thus, the terms and
 * conditions of the GNU General Public License cover the whole
 * combination.
 *    
 * As a special exception, the copyright holders of this library give 
 * you permission to link this library with independent modules to 
 * produce an executable, regardless of the license terms of these 
 * independent modules, and to copy and distribute the resulting 
 * executable under terms of your choice, provided that you also meet, 
 * for each linked independent module, the terms and conditions of the 
 * license of that module.  An independent module is a module which 
 * is not derived from or based on this library.  If you modify this 
 * library, you may extend this exception to your version of the 
 * library, but you are not obligated to do so.  If you do not wish 
 * to do so, delete this exception statement from your version.
 *
 * Project: github.com/rickyepoderi/wbxml-stream
 * 
 */
package es.rickyepoderi.wbxml.stream;

import es.rickyepoderi.wbxml.definition.IanaCharset;
import es.rickyepoderi.wbxml.definition.WbXmlDefinition;
import es.rickyepoderi.wbxml.definition.WbXmlInitialization;
import es.rickyepoderi.wbxml.document.WbXmlAttribute;
import es.rickyepoderi.wbxml.document.WbXmlBody;
import es.rickyepoderi.wbxml.document.WbXmlContent;
import es.rickyepoderi.wbxml.document.WbXmlDocument;
import es.rickyepoderi.wbxml.document.WbXmlElement;
import es.rickyepoderi.wbxml.document.WbXmlEncoder;
import es.rickyepoderi.wbxml.document.WbXmlVersion;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Deque;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.XMLConstants;
import javax.xml.namespace.NamespaceContext;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;

/**
 * 

The XMLStreamWriter interface specifies how to write XML. The XMLStreamWriter * does not perform well formedness checking on its input. However the * writeCharacters method is required to escape & , < and >. For attribute * values the writeAttribute method will escape the above characters plus " * to ensure that all character content and attribute values are well formed. * Each NAMESPACE and ATTRIBUTE must be individually written. The interface is explained in * XMLStreamWriter.

* *

In the WbXml library this stream writer constructs while writing the * memory representation of the WbXmlDocument object (all the elements, * attributes, contents and so on) and in the final writeEndDocument() the * document is encoded in the real output stream. So only in-memory processing * is done until the final method.

* *

Currently the output stream has two possibilities:

* *
    *
  • encoderType: This encoder is the same that the WbXmlEncoder uses. This * means the encoding should be configured to not use the strtbl (NO), * only use it if needed (ID_NEEDED) or always (ALWAYS). By default it is * configured IF_NEEDED.
  • *
  • skipSpaces: if true values which are completely blank spaces are not * considered, and real values are trimmed (start and end). if false all * contents are written to the WBXML. "true" by default.
  • *
* * TODO: Why about create properties to the parser and reader!!! * * @author ricky */ public class WbXmlStreamWriter implements XMLStreamWriter { /** * Private class that queues the parent elements for processing. */ private class ElementContext { private String namespace; private WbXmlElement element; private WbXmlNamespaceContext nsctx; public ElementContext() { this.namespace = null; this.element = null; this.nsctx = null; } public ElementContext(ElementContext e) { this.namespace = e.namespace; this.element = e.element; this.nsctx = e.nsctx; } public ElementContext(WbXmlElement element, String namespace, WbXmlNamespaceContext nsctx) { this.element = element; this.nsctx = nsctx; this.namespace = namespace; } public WbXmlElement getElement() { return element; } public void setElement(WbXmlElement element) { this.element = element; } public WbXmlNamespaceContext getContext() { return nsctx; } public void setContext(WbXmlNamespaceContext nsctx) { this.nsctx = nsctx; } public String getNamespace() { return namespace; } public void setNamespace(String namespace) { this.namespace = namespace; } } /** * logger for the class. */ private static final Logger log = Logger.getLogger(WbXmlStreamWriter.class.getName()); /** * Stream to write the wbxml */ private OutputStream stream; /** * User namespace context */ private NamespaceContext userctx; /** * The document which is being constructed on the fly */ private WbXmlDocument doc; /** * The parents queued to continue the in-memory encoding */ private Deque parents; /** * Current element being encoded */ private ElementContext current; /** * Boolean value that marks if the document is already encoded */ private boolean encoded; /** * The definition used in the document */ private WbXmlDefinition def; /** * The type of encoding it is being used by the writer */ private WbXmlEncoder.StrtblType encoderType; /** * Boolean that marks if the writer should considers whitespaces or not */ private boolean skipSpaces = true; /** * The encoding to use when no specified in the writeStartDocument */ private String encoding = null; /** * Constructor using all the input values: output stream, language definition, * type of encoding and boolean to set skip spaces or not and the encoding. * @param os The Ouput Stream to write the WBXML to * @param def The language definition to use * @param encoderType The type of encoding to perform (strtbl use) * @param skipSpaces The parser skip spaces or consider them * @param encoding Encoding to use when not specified in start document */ public WbXmlStreamWriter(OutputStream os, WbXmlDefinition def, WbXmlEncoder.StrtblType encoderType, boolean skipSpaces, String encoding) { this.stream = os; this.current = new ElementContext(); this.current.setContext(new WbXmlNamespaceContext()); this.userctx = null; this.doc = null; this.parents = new ArrayDeque(); this.encoded = false; this.def = def; this.encoderType = encoderType; this.skipSpaces = skipSpaces; this.encoding = encoding; } /** * Constructor using all the input values: output stream, language definition, * type of encoding and boolean to set skip spaces or not. * @param os The Ouput Stream to write the WBXML to * @param def The language definition to use * @param encoderType The type of encoding to perform (strtbl use) * @param skipSpaces The parser skip spaces or consider them */ public WbXmlStreamWriter(OutputStream os, WbXmlDefinition def, WbXmlEncoder.StrtblType encoderType, boolean skipSpaces) { this(os, def, encoderType, skipSpaces, "UTF-8"); } /** * Constructor with only stream and language definition. Encoder type * is IF_NEEDED and spaces are skipped. * @param os The ouput stream to write the WBXML to * @param def The language definition to use */ public WbXmlStreamWriter(OutputStream os, WbXmlDefinition def) { this(os, def, WbXmlEncoder.StrtblType.IF_NEEDED, true, "UTF-8"); } /** * Constructor only using the ouput stream. The language is guessed * using the root element or DOCTYPE definition. * @param os The language definition to use */ public WbXmlStreamWriter(OutputStream os) { this(os, null, WbXmlEncoder.StrtblType.IF_NEEDED, true, "UTF-8"); } // START DOCUMENT /** * Write the XML Declaration. Defaults the WBXML version to 1.3, and the encoding to utf-8 * @throws XMLStreamException */ @Override public void writeStartDocument() throws XMLStreamException { log.fine("writeStartDocument()"); writeStartDocument(this.encoding, null); } /** * Write the XML Declaration. Defaults the WBXML to 1.3 (other versions * not supported) * @param version version of the xml document * @throws XMLStreamException */ @Override public void writeStartDocument(String version) throws XMLStreamException { log.log(Level.FINE, "writeStartDocument({0})", version); writeStartDocument(this.encoding, null); } /** * Write the XML Declaration. Defaults the XML version to 1.0, and the * encoding to utf-8. In WBXML stream the version is always set to 1.3 * (other versions are not supported). * @param encoding encoding of the xml declaration * @param version version of the xml document * @throws XMLStreamException If given encoding does not match encoding of the underlying stream */ @Override public void writeStartDocument(String encoding, String version) throws XMLStreamException { log.log(Level.FINE, "writeStartDocument({0}, {1})", new Object[] {encoding, version}); if (encoding == null) { encoding = this.encoding; } doc = new WbXmlDocument(WbXmlVersion.VERSION_1_3, IanaCharset.getIanaCharset(encoding)); if (def != null) { log.log(Level.FINE, "Setting definition {0}", def.getName()); doc.setDefinition(def); } } /** * Writes a start tag to the output. All writeStartElement methods open a * new scope in the internal namespace context. Writing the corresponding * EndElement causes the scope to be closed * @param localName local name of the tag, may not be null * @throws XMLStreamException */ @Override public void writeStartElement(String localName) throws XMLStreamException { writeStartElement(null, localName, null); } /** * Writes a start tag to the output * @param namespaceURI the namespaceURI of the prefix to use, may not be null * @param localName local name of the tag, may not be null * @throws XMLStreamException */ @Override public void writeStartElement(String namespaceURI, String localName) throws XMLStreamException { writeStartElement(null, localName, namespaceURI); } /** * Writes a start tag to the output. This is the only method implemented of * this king (all other versions finally call this one). Different implementations * uses this method differently, so it is thought very versatile. The prefix * or namespace of the tag is obtained from the arguments (prefix or namespace) * and if they are not passed is inherited from the parent element.If the * caller later call writeNamespace then the namespace is reassigned. The element * is not written here (cos later namespaces could be set), it is written in the * end element. * @param prefix local name of the tag, may not be null * @param localName the prefix of the tag, may not be null * @param namespaceURI the uri to bind the prefix to, may not be null * @throws XMLStreamException */ @Override public void writeStartElement(String prefix, String localName, String namespaceURI) throws XMLStreamException { log.log(Level.FINE, "writeStartElement({0}, {1}, {2})", new Object[] {prefix, localName, namespaceURI}); // if definition is not already guessed get it using the root element if (def == null) { def = WbXmlInitialization.getDefinitionByRoot(localName, namespaceURI); if (def == null) { throw new XMLStreamException(String.format("Definition not found for root element '%s'", localName)); } log.log(Level.FINE, "Setting definition {0}", def.getName()); doc.setDefinition(def); } // if there is a current element set to parent for later adding ElementContext parent = new ElementContext(current); // parent can be the current element or first parent in queue if (parent.getElement() == null) { // peek the parent parent = this.parents.peek(); } else { // put the element as in the parent queue parents.push(parent); } // sometimes localName is already prefixed int idx = localName.indexOf(':'); if (idx >= 0) { prefix = localName.substring(0, idx); localName = localName.substring(idx + 1); } // create the tag always prefix:localName if (prefix != null && !prefix.isEmpty()) { localName = new StringBuilder(prefix).append(":").append(localName).toString(); } // create a new current element with this tag current.setElement(new WbXmlElement(localName)); // add the current element to the parent or to the doc if (parent != null && parent.getElement() != null) { parent.getElement().addContent(new WbXmlContent(current.getElement())); } else { // first element => add to doc if (doc.getBody() != null) { throw new XMLStreamException(String.format("Trying to add a second root element '%s'", localName)); } doc.setBody(new WbXmlBody(current.getElement())); } } /** * Writes an empty element tag to the output * @param localName local name of the tag, may not be null * @throws XMLStreamException */ @Override public void writeEmptyElement(String localName) throws XMLStreamException { writeEmptyElement(null, localName, null); } /** * Writes an empty element tag to the output * @param namespaceURI the uri to bind the tag to, may not be null * @param localName local name of the tag, may not be null * @throws XMLStreamException */ @Override public void writeEmptyElement(String namespaceURI, String localName) throws XMLStreamException { writeEmptyElement(null, localName, null); } /** * Writes an empty element tag to the output. Not implemented (cos if there * are namespaces it does not work). * @param prefix the prefix of the tag, may not be null * @param localName local name of the tag, may not be null * @param namespaceURI the uri to bind the tag to, may not be null * @throws XMLStreamException */ @Override public void writeEmptyElement(String prefix, String localName, String namespaceURI) throws XMLStreamException { log.log(Level.FINE, "writeEmptyElement({0}, {1}, {2})", new Object[]{prefix, localName, namespaceURI}); // supposing that you can write a xmlns in an empty tag calculateAndNextTag(); } /** * Calculates the tag based on current nsctx and advance the current * position to the parent element if parents exist. */ private void calculateAndNextTag() { // at the end of the element all the namespaces are correct String localName = current.getElement().getTag(); String prefix = null; String namespaceURI = current.getNamespace(); // sometimes localName is already prefixed: clean int idx = localName.indexOf(':'); if (idx >= 0) { prefix = localName.substring(0, idx); localName = localName.substring(idx + 1); } // locate the prefix if used if (namespaceURI != null && !namespaceURI.isEmpty()) { // using the namespace directly prefix = def.getPrefixWithLinked(namespaceURI); } else if (prefix != null && !prefix.isEmpty()) { // using the prefix namespaceURI = current.getContext().getNamespaceURI(prefix); if (namespaceURI != null) { prefix = def.getPrefixWithLinked(namespaceURI); } } else { // using default namespace for this element if (current.getContext().isDefaultNamespaceDefined()) { prefix = def.getPrefixWithLinked(current.getContext().getDefaultNamespace()); } } if (prefix != null && !prefix.isEmpty()) { localName = new StringBuilder(prefix).append(":").append(localName).toString(); } // set the proper tag name current.getElement().setTag(localName); // next element is the parent or null if (this.parents.isEmpty()) { current = new ElementContext(); } else { current = this.parents.pop(); } } /** * Writes an end tag to the output relying on the internal state of the * writer to determine the prefix and local name of the event. In the * current implementation it completes the current element with proper * prefix and localName (cos now all the namespaces are correctly set). * @throws XMLStreamException */ @Override public void writeEndElement() throws XMLStreamException { log.log(Level.FINE, "writeEndElement()"); calculateAndNextTag(); } /** * Closes any start tags and writes corresponding end tags. In the WBXML * implementation the method also performs the real encoding of the WbXmlDocument * object (all the previous staff just construct in memory/Java * representation object). * @throws XMLStreamException Some error performing the real encode */ @Override public void writeEndDocument() throws XMLStreamException { log.log(Level.FINE, "writeEndDocument()"); // close any pendind tags while (current.getElement() != null) { writeEndElement(); } // encode the resulting document try { WbXmlEncoder encoder = new WbXmlEncoder(stream, doc, encoderType); //System.err.println(doc); encoder.encode(); encoded = true; } catch (IOException e) { throw new XMLStreamException("Error encoding the WbXML document", e); } } /** * Close this writer and free any resources associated with the writer. * This must not close the underlying output stream. * @throws XMLStreamException */ @Override public void close() throws XMLStreamException { //try { // log.log(Level.FINE, "flush()"); // this.stream.close(); //} catch (IOException e) { // throw new XMLStreamException("Error closing the stream", e); //} } /** * Write any cached data to the underlying output mechanism. The method * only flush the real stream if encoded. * @throws XMLStreamException */ @Override public void flush() throws XMLStreamException { try { log.log(Level.FINE, "flush()"); if (encoded) { this.stream.flush(); } } catch (IOException e) { throw new XMLStreamException("Error flushing the stream", e); } } /** * Writes an attribute to the output stream without a prefix * @param localName the local name of the attribute * @param value the value of the attribute * @throws XMLStreamException */ @Override public void writeAttribute(String localName, String value) throws XMLStreamException { writeAttribute(null, null, localName, value); } /** * Writes an attribute to the output stream * @param namespaceURI the uri of the prefix for this attribute * @param localName the local name of the attribute * @param value the value of the attribute * @throws XMLStreamException */ @Override public void writeAttribute(String namespaceURI, String localName, String value) throws XMLStreamException { writeAttribute(null, namespaceURI, localName, value); } /** * Writes an attribute to the output stream. The real method that all the * other variants call. As in writeStartElement it tries to be very * versatile cos different implementations (jaxb, transformer,...) uses * it quite differently. * @param prefix the prefix for this attribute * @param namespaceURI the uri of the prefix for this attribute * @param localName the local name of the attribute * @param value the value of the attribute * @throws XMLStreamException */ @Override public void writeAttribute(String prefix, String namespaceURI, String localName, String value) throws XMLStreamException { log.log(Level.FINE, "writeAttribute({0}, {1}, {2}, {3})", new Object[]{prefix, namespaceURI, localName, value}); // sometimes localName is already prefixed: clean int idx = localName.indexOf(':'); if (idx >= 0) { prefix = localName.substring(0, idx); localName = localName.substring(idx + 1); } // locate the prefix if namespace defined if (namespaceURI != null && !namespaceURI.isEmpty()) { // namespace used directly prefix = def.getPrefixWithLinked(namespaceURI); } else if (prefix != null && !prefix.isEmpty()) { // using the prefix namespaceURI = current.getContext().getNamespaceURI(prefix); if (namespaceURI != null) { prefix = def.getPrefixWithLinked(namespaceURI); } } else { // using previous namespace if inherited //prefix = currentElement.getTagPrefix(); if (current.getContext().isDefaultNamespaceDefined()) { prefix = def.getPrefix(current.getContext().getDefaultNamespace()); } } if (prefix != null && !prefix.isEmpty()) { localName = new StringBuilder(prefix).append(":").append(localName).toString(); } // add an atribute to the current element if (current.getElement() == null) { throw new XMLStreamException(String.format("No elemento to add the attribute '%s'='%s' to", localName, value)); } current.getElement().addAttribute(new WbXmlAttribute(localName, value)); } /** * Writes a namespace to the output stream If the prefix argument to this * method is the empty string, "xmlns", or null this method will delegate * to writeDefaultNamespace. In the WBXML implementation the prefix * of the current element is updated to the one passed. * @param prefix the prefix to bind this namespace to * @param namespaceURI the uri to bind the prefix to * @throws XMLStreamException */ @Override public void writeNamespace(String prefix, String namespaceURI) throws XMLStreamException { log.log(Level.FINE, "writeNamespace({0}, {1})", new Object[]{prefix, namespaceURI}); if (namespaceURI == null || namespaceURI.isEmpty()) { //throw new XMLStreamException("namespaceURI cannot be null!"); return; } if (prefix == null || prefix.isEmpty() || prefix.equals(XMLConstants.XMLNS_ATTRIBUTE)) { // default namespace for the document if (current.getElement() != null) { current.setContext(current.getContext().clone()); current.getContext().setDefaultNamespace(namespaceURI); } } else { if (def.getPrefixWithLinked(namespaceURI) == null) { throw new XMLStreamException( String.format("namespaceURI '%s' is not defined in the WbXML definition", namespaceURI)); } // add it current.setContext(current.getContext().clone()); current.getContext().addPrefix(prefix, namespaceURI); } } /** * Writes the default namespace to the stream. * @param namespaceURI the uri to bind the default namespace to * @throws XMLStreamException */ @Override public void writeDefaultNamespace(String namespaceURI) throws XMLStreamException { log.log(Level.FINE, "writeDefaultNamespace({0})", namespaceURI); writeNamespace(XMLConstants.XMLNS_ATTRIBUTE, namespaceURI); } /** * Writes an xml comment with the data enclosed. Nothing is done cos WBXML * does not use comments. * @param data the data contained in the comment, may be null * @throws XMLStreamException */ @Override public void writeComment(String data) throws XMLStreamException { log.log(Level.FINE, "writeComment({0})", data); // no comment to write in wbxml } /** * Writes a processing instruction. * NOTE: Not implemented, throws an exception * @param target the target of the processing instruction, may not be null * @throws XMLStreamException */ @Override public void writeProcessingInstruction(String target) throws XMLStreamException { throw new UnsupportedOperationException("Not supported yet."); } /** * Writes a processing instruction. * NOTE: Not implemented, throws an exception * @param target the target of the processing instruction, may not be null * @param data the data contained in the processing instruction, may not be null * @throws XMLStreamException */ @Override public void writeProcessingInstruction(String target, String data) throws XMLStreamException { throw new UnsupportedOperationException("Not supported yet."); } /** * Writes a CData section. In delegates to writeCharsInternal. * @param data the data contained in the CData Section, may not be null * @throws XMLStreamException */ @Override public void writeCData(String data) throws XMLStreamException { log.log(Level.FINE, "writeCData({0})", data); writeCharsInternal(data, false); } /** * Write a DTD section. This string represents the entire doctypedecl * production from the XML 1.0 specification. Nothing is really written * just it is used to guess the language definition if it was not passed * in the constructor. * @param dtd the DTD to be written * @throws XMLStreamException */ @Override public void writeDTD(String dtd) throws XMLStreamException { log.log(Level.FINE, "writeDTD({0})", dtd); // get definition if not chosen based on the formal public identifier (FPI) or root element if (def == null) { // the format is: // // ]> int idxRoot = dtd.indexOf(" 0 && idxEndRoot > idxRoot && idxFPI > idxEndRoot && idxEndFPI > idxFPI) { String root = dtd.substring(idxRoot, idxEndRoot).trim(); String fpi = dtd.substring(idxFPI, idxEndFPI); // try first using the FPI def = WbXmlInitialization.getDefinitionByFPI(fpi); log.log(Level.FINE, "FPI: {0}", def.getName()); if (def == null) { def = WbXmlInitialization.getDefinitionByRoot(root, null); log.log(Level.FINE, "root: {0}", def.getName()); } if (def != null) { doc.setDefinition(def); } } } } /** * Writes an entity reference. * NOTE: Not implemented, it should write the reference char or the * real data corresponding to the entity (WBXML only admits numeric entities). * @param name the name of the entity * @throws XMLStreamException */ @Override public void writeEntityRef(String name) throws XMLStreamException { throw new UnsupportedOperationException("Not supported yet."); } /** * Private method that skips whitespaces at the beginning of the data. * @param data The data to skip spaces from the beginning * @return The data with the whitespaces skipped */ static private char[] skipWhitespacesPrefix(char[] data) { for (int i = 0; i < data.length; i++) { if (!XMLChar.isSpace(data[i])) { if (i == 0) { return data; } else { return Arrays.copyOfRange(data, i, data.length); } } } return new char[0]; } /** * Private method that skips whitespaces at the end of the data. * @param data The data to skip spaces from the end * @return The data with the whitespaces skipped */ static private char[] skipWhitespacesSuffix(char[] data) { for (int i = data.length - 1; i >= 0; i--) { if (!XMLChar.isSpace(data[i])) { if (i == data.length - 1) { return data; } else { return Arrays.copyOfRange(data, 0, i+1); } } } return new char[0]; } /** * Private method that trims whitespaces from the beginning and the end. * It calls to the other two methods. * @param data The data to skip spaces * @return The data with the whitespaces skipped */ static private char[] skipWhitespaces(char[] data) { data = skipWhitespacesPrefix(data); data = skipWhitespacesSuffix(data); return data; } /** * Private method that writes the chars skipping the whitespaces if needed * @param text The test to write * @param skip true if whitespaces should be skipped, false if not */ private void writeCharsInternal(String text, boolean skip) { log.log(Level.FINE, "writeCharsInternal({0})", text); if (current.getElement() != null) { //throw new XMLStreamException(String.format("No element to add the text '%s' to", text)); if (skip) { text = new String(skipWhitespaces(text.toCharArray())); if (!text.isEmpty()) { current.getElement().addContent(new WbXmlContent(text)); } else { log.log(Level.FINE, "Skipping characters {0}", text); } } else { // just create a text content in the current element current.getElement().addContent(new WbXmlContent(text)); } } } /** * Write text to the output. * @param text the value to write * @throws XMLStreamException */ @Override public void writeCharacters(String text) throws XMLStreamException { log.log(Level.FINE, "writeCharacters({0})", text); writeCharsInternal(text, skipSpaces); } /** * Write text to the output * @param text the value to write * @param start the starting position in the array * @param len the number of characters to write * @throws XMLStreamException */ @Override public void writeCharacters(char[] text, int start, int len) throws XMLStreamException { log.log(Level.FINE, "writeCharacters({0}, {1}, {2})", new Object[]{text, start, len}); writeCharsInternal(new String(text, start, len), skipSpaces); } /** * Gets the prefix the uri is bound to * @param uri the prefix or null * @return The namespace associated to the prefix * @throws XMLStreamException */ @Override public String getPrefix(String uri) throws XMLStreamException { log.log(Level.FINE, "getPrefix({0})", uri); String res = current.getContext().getPrefix(uri); if (res == null && this.userctx != null) { res = this.userctx.getPrefix(uri); } return res; } /** * Sets the prefix the uri is bound to. This prefix is bound in the scope * of the current START_ELEMENT / END_ELEMENT pair. If this method is called * before a START_ELEMENT has been written the prefix is bound in the root * scope. * @param prefix the prefix to bind to the uri, may not be null * @param uri the uri to bind to the prefix, may be null * @throws XMLStreamException */ @Override public void setPrefix(String prefix, String uri) throws XMLStreamException { log.log(Level.FINE, "setPrefix({0}, {1})", new Object[]{prefix, uri}); if (prefix == null) { throw new XMLStreamException("Prefix cannot be null"); } if (uri == null) { throw new XMLStreamException("URI cannot be null"); } current.setContext(current.getContext().clone()); current.getContext().addPrefix(prefix, uri); } /** * Binds a URI to the default namespace This URI is bound in the scope of * the current START_ELEMENT / END_ELEMENT pair. If this method is called * before a START_ELEMENT has been written the uri is bound in the root scope. * @param namespaceURI the uri to bind to the default namespace, may be null * @throws XMLStreamException */ @Override public void setDefaultNamespace(String namespaceURI) throws XMLStreamException { log.log(Level.FINE, "setDefaultNamespace({0})", namespaceURI); current.setContext(current.getContext().clone()); current.getContext().setDefaultNamespace(namespaceURI); } /** * Sets the current namespace context for prefix and uri bindings. This * context becomes the root namespace context for writing and will replace * the current root namespace context. Subsequent calls to setPrefix and * setDefaultNamespace will bind namespaces using the context passed to the * method as the root context for resolving namespaces. This method may only * be called once at the start of the document. It does not cause the * namespaces to be declared. If a namespace URI to prefix mapping is found * in the namespace context it is treated as declared and the prefix may * be used by the StreamWriter. * @param nc the namespace context to use for this writer, may not be null * @throws XMLStreamException */ @Override public void setNamespaceContext(NamespaceContext nc) throws XMLStreamException { log.log(Level.FINE, "setNamespaceContext({0})", nc); this.userctx = nc; } /** * Returns the current namespace context. * @return the current NamespaceContext */ @Override public NamespaceContext getNamespaceContext() { log.fine("getNamespaceContext()"); return current.getContext(); } /** * Get the value of a feature/property from the underlying implementation * NOTE: Not implemented, it throws an exception * @param string The name of the property, may not be null * @return The value of the property * @throws IllegalArgumentException */ @Override public Object getProperty(String string) throws IllegalArgumentException { throw new UnsupportedOperationException("Not supported yet."); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy