blob: 51189bba299e0df8ed83ef3d50fabaf0c844039f [file] [log] [blame]
/*
* 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.util;
import org.apache.axiom.om.OMAttribute;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMNamespace;
import org.apache.axiom.om.OMNode;
import org.apache.axiom.om.impl.OMNodeEx;
import org.apache.axiom.om.impl.serialize.StreamingOMSerializer;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import java.util.Iterator;
public class OMSerializerUtil {
static long nsCounter = 0;
/**
* Method serializeEndpart.
*
* @param writer
* @throws javax.xml.stream.XMLStreamException
*
*/
public static void serializeEndpart(XMLStreamWriter writer)
throws XMLStreamException {
writer.writeEndElement();
}
/**
* Method serializeAttribute.
*
* @param attr
* @param writer
* @throws XMLStreamException
*/
public static void serializeAttribute(OMAttribute attr, XMLStreamWriter writer)
throws XMLStreamException {
// first check whether the attribute is associated with a namespace
OMNamespace ns = attr.getNamespace();
String prefix = null;
String namespaceName = null;
if (ns != null) {
// add the prefix if it's availble
prefix = ns.getPrefix();
namespaceName = ns.getName();
if (prefix != null) {
writer.writeAttribute(prefix, namespaceName,
attr.getLocalName(), attr.getAttributeValue());
} else {
writer.writeAttribute(namespaceName, attr.getLocalName(),
attr.getAttributeValue());
}
} else {
String localName = attr.getLocalName();
String attributeValue = attr.getAttributeValue();
writer.writeAttribute(localName, attributeValue);
}
}
/**
* Method serializeNamespace.
*
* @param namespace
* @param writer
* @throws XMLStreamException
*/
public static void serializeNamespace(OMNamespace namespace, XMLStreamWriter writer)
throws XMLStreamException {
if (namespace == null) {
return;
}
String uri = namespace.getName();
String prefix = namespace.getPrefix();
if (uri != null && !"".equals(uri)) {
String prefixFromWriter = writer.getPrefix(uri);
// Handling Default Namespaces First
// Case 1 :
// here we are trying define a default namespace. But has this been defined in the current context.
// yes, there can be a default namespace, but it may have a different URI. If its a different URI
// then explicitly define the default namespace here.
// Case 2 :
// The passed in namespace is a default ns, but there is a non-default ns declared
// in the current scope.
if (("".equals(prefix) && "".equals(prefixFromWriter) && !uri.equals(writer.getNamespaceContext().getNamespaceURI(""))) ||
(prefix != null && "".equals(prefix) && (prefixFromWriter == null || !prefix.equals(prefixFromWriter))))
{
// this has not been declared earlier
writer.writeDefaultNamespace(uri);
writer.setDefaultNamespace(uri);
} else {
prefix = prefix == null ? getNextNSPrefix(writer) : prefix;
if (prefix != null && !prefix.equals(prefixFromWriter) && !checkForPrefixInTheCurrentContext(writer, uri, prefix))
{
writer.writeNamespace(prefix, uri);
writer.setPrefix(prefix, uri);
}
}
}
}
/**
* Method serializeStartpart.
*
* @param writer
* @throws XMLStreamException
*/
public static void serializeStartpart
(OMElement
element, XMLStreamWriter writer)
throws XMLStreamException {
String nameSpaceName;
String writer_prefix;
String prefix;
if (element.getNamespace() != null) {
nameSpaceName = element.getNamespace().getName();
prefix = element.getNamespace().getPrefix();
if (nameSpaceName != null && !"".equals(nameSpaceName)) {
writer_prefix = writer.getPrefix(nameSpaceName);
// if the writer has no prefix registered for the given namespace, no matter what prefix the
// ns contains, use that to handle the ns
if (writer_prefix == null && !"".equals(prefix)) {
prefix = (prefix == null) ? getNextNSPrefix(writer) : prefix;
writer.writeStartElement(prefix, element.getLocalName(),
nameSpaceName);
writer.writeNamespace(prefix, nameSpaceName);
writer.setPrefix(prefix, nameSpaceName);
} else if (prefix == null) {
// by this time prefix is null and writer_prefix is not null
writer.writeStartElement(nameSpaceName,
element.getLocalName());
} else {
// now lets handle the case where (prefix != null && writer_prefix != null)
if ("".equals(prefix) && "".equals(writer_prefix)) {
// now this element is trying to use a default namespace and at the same point
// exists a default namespace with the given ns URI.
// but the problem here is that, what if the xml is like the following
// <One xmlns="one.org" >
// <Two xmlns="two.org">
// <Three xmlns="one.org" />
// </Two>
// </One>
//
// if we ask the prefix registered with one.org, the parser will return ""
// which is the default ns. But if we do not declare a new default ns explicitly here
// then this causes problem as element Two has already overriden the default ns.
//
// Solution for this is to ask from the parser the nsURI attached to "" at this
// moment and compare the return uri with namespace name
if (nameSpaceName.equals(writer.getNamespaceContext().getNamespaceURI("")))
{
writer.writeStartElement(nameSpaceName, element.getLocalName());
} else {
writer.writeStartElement(prefix, element.getLocalName(),
nameSpaceName);
writer.writeDefaultNamespace(nameSpaceName);
writer.setDefaultNamespace(nameSpaceName);
}
} else if (prefix.equals(writer_prefix)) {
writer.writeStartElement(nameSpaceName, element.getLocalName());
} else if ("".equals(prefix)) {
writer.writeStartElement(prefix, element.getLocalName(),
nameSpaceName);
writer.writeDefaultNamespace(nameSpaceName);
writer.setDefaultNamespace(nameSpaceName);
} else {
// now the left scenario is this
// 1. prefix != "" && writer_prefix != "" but writer_prefix != prefix
// 2. prefix != "" && writer_prefix == ""
// In both the above cases this xml may contain more than one prefix for the
// same URI. Check them all.
// this flag will remember whether this ns is declared in the scope with the
// given prefix or not
boolean found = checkForPrefixInTheCurrentContext(writer, nameSpaceName, prefix);
if (!found) {
// seems we haven't found one in the current scope. So declare it.
writer.writeStartElement(prefix, element.getLocalName(),
nameSpaceName);
writer.writeNamespace(prefix, nameSpaceName);
writer.setPrefix(prefix, nameSpaceName);
} else {
writer.writeStartElement(prefix, element.getLocalName(), nameSpaceName);
}
}
}
} else {
writer.writeStartElement(element.getLocalName());
}
} else {
writer.writeStartElement(element.getLocalName());
/** // we need to check whether there's a default namespace visible at this point because
// otherwise this element will go into that namespace unintentionally. So we check
// whether there is a default NS visible and if so turn it off.
if (writer.getNamespaceContext().getNamespaceURI("") != null) {
writer.writeDefaultNamespace("");
} */
}
// add the namespaces
serializeNamespaces(element, writer);
// add the elements attributes
serializeAttributes(element, writer);
}
private static boolean checkForPrefixInTheCurrentContext(XMLStreamWriter writer, String nameSpaceName, String prefix) throws XMLStreamException {
Iterator prefixesIter = writer.getNamespaceContext().getPrefixes(nameSpaceName);
while (prefixesIter.hasNext()) {
String prefix_w = (String) prefixesIter.next();
if (prefix_w.equals(prefix)) {
// if found do not declare the ns
return true;
}
}
return false;
}
public static void serializeNamespaces
(OMElement
element,
XMLStreamWriter writer) throws XMLStreamException {
Iterator namespaces = element.getAllDeclaredNamespaces();
if (namespaces != null) {
while (namespaces.hasNext()) {
serializeNamespace((OMNamespace) namespaces.next(), writer);
}
}
}
public static void serializeAttributes
(OMElement
element,
XMLStreamWriter writer) throws XMLStreamException {
Iterator attributes = element.getAllAttributes();
if (attributes != null && attributes.hasNext()) {
while (attributes.hasNext()) {
serializeAttribute((OMAttribute) attributes.next(),
writer);
}
}
}
/**
* Method serializeNormal.
*
* @param writer
* @param cache
* @throws XMLStreamException
*/
public static void serializeNormal
(OMElement
element, XMLStreamWriter writer, boolean cache)
throws XMLStreamException {
if (cache) {
element.build();
}
serializeStartpart(element, writer);
OMNode firstChild = element.getFirstOMChild();
if (firstChild != null) {
if (cache) {
((OMNodeEx) firstChild).serialize(writer);
} else {
((OMNodeEx) firstChild).serializeAndConsume(writer);
}
}
serializeEndpart(writer);
}
public static void serializeByPullStream
(OMElement
element, XMLStreamWriter writer) throws XMLStreamException {
serializeByPullStream(element, writer, false);
}
public static void serializeByPullStream
(OMElement
element, XMLStreamWriter writer, boolean cache) throws XMLStreamException {
StreamingOMSerializer streamingOMSerializer = new StreamingOMSerializer();
if (cache) {
streamingOMSerializer.serialize(element.getXMLStreamReader(),
writer);
} else {
XMLStreamReader xmlStreamReaderWithoutCaching = element.getXMLStreamReaderWithoutCaching();
streamingOMSerializer.serialize(xmlStreamReaderWithoutCaching,
writer);
}
}
public static String getNextNSPrefix() {
return "axis2ns" + ++nsCounter % Long.MAX_VALUE;
}
public static String getNextNSPrefix(XMLStreamWriter writer) {
String prefix = getNextNSPrefix();
while (writer.getNamespaceContext().getNamespaceURI(prefix) != null) {
prefix = getNextNSPrefix();
}
return prefix;
}
}