org.apache.axiom.om.impl.serialize.StreamingOMSerializer Maven / Gradle / Ivy
/*
* Copyright 2004,2005 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.axiom.om.impl.serialize;
import java.util.ArrayList;
import org.apache.axiom.om.OMSerializer;
import org.apache.axiom.om.impl.util.OMSerializerUtil;
import javax.xml.namespace.NamespaceContext;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
/**
* Class StreamingOMSerializer
*/
public class StreamingOMSerializer implements XMLStreamConstants, OMSerializer {
private static int namespaceSuffix = 0;
public static final String NAMESPACE_PREFIX = "ns";
/*
* The behavior of the serializer is such that it returns when it encounters the
* starting element for the second time. The depth variable tracks the depth of the
* serilizer and tells it when to return.
* Note that it is assumed that this serialization starts on an Element.
*/
/**
* Field depth
*/
private int depth = 0;
/**
* Method serialize.
*
* @param node
* @param writer
* @throws XMLStreamException
*/
public void serialize(XMLStreamReader node, XMLStreamWriter writer)
throws XMLStreamException {
serializeNode(node, writer);
}
/**
* Method serializeNode.
*
* @param reader
* @param writer
* @throws XMLStreamException
*/
protected void serializeNode(XMLStreamReader reader, XMLStreamWriter writer)
throws XMLStreamException {
//TODO We get the StAXWriter at this point and uses it hereafter assuming that this is the only entry point to this class.
// If there can be other classes calling methodes of this we might need to change methode signatures to OMOutputer
while (reader.hasNext()) {
int event = reader.next();
if (event == START_ELEMENT) {
serializeElement(reader, writer);
depth++;
} else if (event == ATTRIBUTE) {
serializeAttributes(reader, writer);
} else if (event == CHARACTERS) {
serializeText(reader, writer);
} else if (event == COMMENT) {
serializeComment(reader, writer);
} else if (event == CDATA) {
serializeCData(reader, writer);
} else if (event == END_ELEMENT) {
serializeEndElement(writer);
depth--;
}else if (event == START_DOCUMENT) {
depth++; //if a start document is found then increment the depth
} else if (event == END_DOCUMENT) {
if (depth!=0) depth--; //for the end document - reduce the depth
try {
serializeEndElement(writer);
} catch (Exception e) {
//TODO: log exceptions
}
}
if (depth == 0) {
break;
}
}
}
/**
* @param reader
* @param writer
* @throws XMLStreamException
*/
protected void serializeElement(XMLStreamReader reader,
XMLStreamWriter writer)
throws XMLStreamException {
// Note: To serialize the start tag, we must follow the order dictated by the JSR-173 (StAX) specification.
// Please keep this code in sync with the code in OMSerializerUtil.serializeStartpart
// The algorithm is:
// ... generate setPrefix/setDefaultNamespace for each namespace declaration if the prefix is unassociated.
// ... generate setPrefix/setDefaultNamespace if the prefix of the element is unassociated
// ... generate setPrefix/setDefaultNamespace for each unassociated prefix of the attributes.
//
// ... generate writeStartElement (See NOTE_A)
//
// ... generate writeNamespace/writerDefaultNamespace for the new namespace declarations determine during the "set" processing
// ... generate writeAttribute for each attribute
// NOTE_A: To confuse matters, some StAX vendors (including woodstox), believe that the setPrefix bindings
// should occur after the writeStartElement. If this is the case, the writeStartElement is generated first.
ArrayList writePrefixList = null;
ArrayList writeNSList = null;
// Get the prefix and namespace of the element. "" and null are identical.
String ePrefix = reader.getPrefix();
ePrefix = (ePrefix != null && ePrefix.length() == 0) ? null : ePrefix;
String eNamespace = reader.getNamespaceURI();
eNamespace = (eNamespace != null && eNamespace.length() == 0) ? null : eNamespace;
// Write the startElement if required
boolean setPrefixFirst = OMSerializerUtil.isSetPrefixBeforeStartElement(writer);
if (!setPrefixFirst) {
if (eNamespace != null) {
if (ePrefix == null) {
writer.writeStartElement("", reader.getLocalName(), eNamespace);
} else {
writer.writeStartElement(ePrefix, reader.getLocalName(), eNamespace);
}
} else {
writer.writeStartElement(reader.getLocalName());
}
}
// Generate setPrefix for the namespace declarations
int count = reader.getNamespaceCount();
for (int i = 0; i < count; i++) {
String prefix = reader.getNamespacePrefix(i);
prefix = (prefix != null && prefix.length() == 0) ? null : prefix;
String namespace = reader.getNamespaceURI(i);
namespace = (namespace != null && namespace.length() == 0) ? null : namespace;
String newPrefix = generateSetPrefix(prefix, namespace, writer);
// If this is a new association, remember it so that it can written out later
if (newPrefix != null) {
if (writePrefixList == null) {
writePrefixList= new ArrayList();
writeNSList = new ArrayList();
}
if (!writePrefixList.contains(newPrefix)) {
writePrefixList.add(newPrefix);
writeNSList.add(namespace);
}
}
}
// Generate setPrefix for the element
// If the prefix is not associated with a namespace yet, remember it so that we can
// write out a namespace declaration
String newPrefix = generateSetPrefix(ePrefix, eNamespace, writer);
// If this is a new association, remember it so that it can written out later
if (newPrefix != null) {
if (writePrefixList == null) {
writePrefixList= new ArrayList();
writeNSList = new ArrayList();
}
if (!writePrefixList.contains(newPrefix)) {
writePrefixList.add(newPrefix);
writeNSList.add(eNamespace);
}
}
// Now Generate setPrefix for each attribute
count = reader.getAttributeCount();
for (int i = 0; i < count; i++) {
String prefix = reader.getAttributePrefix(i);
prefix = (prefix != null && prefix.length() == 0) ? null : prefix;
String namespace = reader.getAttributeNamespace(i);
namespace = (namespace != null && namespace.length() == 0) ? null : namespace;
// Default prefix referencing is not allowed on an attribute
if (prefix == null && namespace != null) {
String writerPrefix = writer.getPrefix(namespace);
writerPrefix = (writerPrefix != null && writerPrefix.length() == 0) ? null : writerPrefix;
prefix = (writerPrefix != null) ?
writerPrefix :
generateUniquePrefix(writer.getNamespaceContext());
}
newPrefix = generateSetPrefix(prefix, namespace, writer);
// If the prefix is not associated with a namespace yet, remember it so that we can
// write out a namespace declaration
if (newPrefix != null) {
if (writePrefixList == null) {
writePrefixList= new ArrayList();
writeNSList = new ArrayList();
}
if (!writePrefixList.contains(newPrefix)) {
writePrefixList.add(newPrefix);
writeNSList.add(namespace);
}
}
}
// Now write the startElement
if (setPrefixFirst) {
if (eNamespace != null) {
if (ePrefix == null) {
writer.writeStartElement("", reader.getLocalName(), eNamespace);
} else {
writer.writeStartElement(ePrefix, reader.getLocalName(), eNamespace);
}
} else {
writer.writeStartElement(reader.getLocalName());
}
}
// Now write out the list of namespace declarations in this list that we constructed
// while doing the "set" processing.
if (writePrefixList != null) {
for (int i=0; i
© 2015 - 2025 Weber Informatics LLC | Privacy Policy