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

org.apache.axiom.om.impl.util.OMSerializerUtil Maven / Gradle / Ivy

There is a newer version: 1.4.0
Show newest version
/*
 * 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.namespace.NamespaceContext;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import java.util.ArrayList;
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
     * @deprecated use serializeStartpart instead
     */
    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.getNamespaceURI();
            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
     * @deprecated Use serializeStartpart instead
     */
    public static void serializeNamespace(OMNamespace namespace, XMLStreamWriter writer)
            throws XMLStreamException {
        if (namespace == null) {
            return;
        }
        String uri = namespace.getNamespaceURI();
        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);
                }
            }
        } else {
            // now the nsURI passed is "" or null. Meaning we gonna work with defaultNS.
            // check whether there is a defaultNS already declared. If yes, is it the same as this ?
            String currentDefaultNSURI = writer.getNamespaceContext().getNamespaceURI("");
            if( (currentDefaultNSURI != null && !currentDefaultNSURI.equals(uri)) ||
                    uri != null && !uri.equals(currentDefaultNSURI)){
                // this has not been declared earlier
                writer.writeDefaultNamespace(uri);
                writer.setDefaultNamespace(uri);
            }
        }
    }

    /**
     * Unfortunately there is disagreement in the user community about the semantics of
     * setPrefix on the XMLStreamWriter.  An example will explain the difference:
     * writer.startElement("a")
     * writer.setPrefix("pre", "urn://sample")
     * writer.startElement("b")
     * 
     * Some user communities (woodstox) believe that the setPrefix is associate with the scope
     * for "a" and thus remains in scope until the end of a.  The basis for this believe is 
     * XMLStreamWriter javadoc (which some would argue is incomplete).
     * 
     * Some user communities believe that the setPrefix is associated with the "b" element.
     * These communities reference an example in the specification and historical usage of SAX.
     *
     * This method will return true if the setPrefix is associated with the next writeStartElement.
     * 
     * @param writer
     * @return true if setPrefix should be generated before startElement
     */
    public static boolean isSetPrefixBeforeStartElement(XMLStreamWriter writer) {
    	NamespaceContext nc = writer.getNamespaceContext();
    	return(nc ==null || nc.getClass().getName().indexOf("wstx") == -1);
    }
    
    /**
     * Method serializeStartpart.
     * Serialize the start tag of an element.
     *
     * @param element
     * @param writer
     * @throws XMLStreamException
     */
    public static void serializeStartpart(OMElement element, 
    		XMLStreamWriter writer) throws XMLStreamException {
    	serializeStartpart(element, element.getLocalName(), writer);
    }
    
    /**
     * Method serializeStartpart.
     * Serialize the start tag of an element.
     *
     * @param element
     * @param localName (in some cases, the caller wants to force a different localName)
     * @param writer
     * @throws XMLStreamException
     */
    public static void serializeStartpart(OMElement element, String localName, 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 StreamingOMSerializer.serializeElement
    
        // 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 namespace and prefix of the element
    	OMNamespace eOMNamespace = element.getNamespace();
    	String ePrefix = null;
		String eNamespace = null;
		if (eOMNamespace != null) {
			ePrefix = eOMNamespace.getPrefix();
			eNamespace = eOMNamespace.getNamespaceURI();
		}
		ePrefix = (ePrefix != null && ePrefix.length() == 0) ? null : ePrefix;
		eNamespace = (eNamespace != null && eNamespace.length() == 0) ? null : eNamespace;
		
		// Write the startElement if required
		boolean setPrefixFirst = isSetPrefixBeforeStartElement(writer);
        if (!setPrefixFirst) {
        	if (eNamespace != null) {
        		if (ePrefix == null) {
        			writer.writeStartElement("", localName, eNamespace);
        		} else {
        			writer.writeStartElement(ePrefix, localName, eNamespace);
        		}
        	} else {
        		writer.writeStartElement(localName);
        	}
        }
		
    	// Generate setPrefix for the namespace declarations
    	Iterator it = element.getAllDeclaredNamespaces();
    	while (it != null && it.hasNext()) {
    		OMNamespace omNamespace = (OMNamespace) it.next();
    		String prefix = null;
    		String namespace = null;
    		if (omNamespace != null) {
    			prefix = omNamespace.getPrefix();
    			namespace = omNamespace.getNamespaceURI();
    		}
        	prefix = (prefix != null && prefix.length() == 0) ? null : prefix;
        	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
    	// Get the prefix and namespace of the element.  "" and null are identical.
    	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
    	Iterator attrs = element.getAllAttributes();
        while (attrs != null && attrs.hasNext()) {
        	OMAttribute attr = (OMAttribute) attrs.next();
        	OMNamespace omNamespace = attr.getNamespace();
        	String prefix = null;
    		String namespace = null;
    		if (omNamespace != null) {
    			prefix = omNamespace.getPrefix();
    			namespace = omNamespace.getNamespaceURI();
    		}
        	prefix = (prefix != null && prefix.length() == 0) ? null : prefix;
        	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 : getNextNSPrefix();
            }
            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);
        		}
        	}
        }
        
        // Write the startElement if required
        if (setPrefixFirst) {
        	if (eNamespace != null) {
        		if (ePrefix == null) {
        			writer.writeStartElement("", localName, eNamespace);
        		} else {
        			writer.writeStartElement(ePrefix, localName, eNamespace);
        		}
        	} else {
        		writer.writeStartElement(localName);
        	}
        }
        
        // 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 0) {
        		// Disable the default namespace
        		writer.setDefaultNamespace("");
        		newPrefix = "";
        	}
        }
        return newPrefix;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy