com.centeractive.ws.builder.soap.XmlUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.centeractive.ws.builder.soap.XmlUtils.java

Source

/**
 * Copyright (c) 2012 centeractive ag. All Rights Reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301  USA
 */
package com.centeractive.ws.builder.soap;

import com.centeractive.ws.builder.SoapBuilderException;
import net.sf.saxon.expr.Token;
import net.sf.saxon.expr.Tokenizer;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.apache.xml.serialize.OutputFormat;
import org.apache.xml.serialize.XMLSerializer;
import org.apache.xmlbeans.*;
import org.apache.xmlbeans.XmlCursor.TokenType;
import org.w3c.dom.*;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

import javax.xml.namespace.QName;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.StreamResult;
import java.io.*;
import java.net.URL;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.*;

/**
 * This class was extracted from the soapUI code base by centeractive ag in October 2011.
 * The main reason behind the extraction was to separate the code that is responsible
 * for the generation of the SOAP messages from the rest of the soapUI's code that is
 * tightly coupled with other modules, such as soapUI's graphical user interface, etc.
 * The goal was to create an open-source java project whose main responsibility is to
 * handle SOAP message generation and SOAP transmission purely on an XML level.
 * <br/>
 * centeractive ag would like to express strong appreciation to SmartBear Software and
 * to the whole team of soapUI's developers for creating soapUI and for releasing its
 * source code under a free and open-source licence. centeractive ag extracted and
 * modifies some parts of the soapUI's code in good faith, making every effort not
 * to impair any existing functionality and to supplement it according to our
 * requirements, applying best practices of software design.
 *
 * Changes done:
 * - changing location in the package structure
 * - removal of dependencies and code parts that are out of scope of SOAP message generation
 * - minor fixes to make the class compile out of soapUI's code base
 * - adding utility method to handle XML-String from/to XML-Source transformation
 */

/**
 * General XML-related utilities
 */
@SuppressWarnings("deprecation")
public final class XmlUtils {
    private static DocumentBuilder documentBuilder;
    private final static Logger log = Logger.getLogger(XmlUtils.class);

    static synchronized public Document parse(InputStream in) {
        try {
            return ensureDocumentBuilder().parse(in);
        } catch (Exception e) {
            log.error("Error parsing InputStream; " + e.getMessage(), e);
        }

        return null;
    }

    static synchronized public Document parse(String fileName) throws IOException {
        try {
            return ensureDocumentBuilder().parse(fileName);
        } catch (SAXException e) {
            log.error("Error parsing fileName [" + fileName + "]; " + e.getMessage(), e);
        }

        return null;
    }

    public static String entitize(String xml) {
        return xml.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;")
                .replaceAll("\"", "&quot;").replaceAll("'", "&apos;");
    }

    public static String entitizeContent(String xml) {
        return xml.replaceAll("&", "&amp;").replaceAll("\"", "&quot;").replaceAll("'", "&apos;");
    }

    static synchronized public Document parse(InputSource inputSource) throws IOException {
        try {
            return ensureDocumentBuilder().parse(inputSource);
        } catch (SAXException e) {
            throw new IOException(e.toString());
        }
    }

    private static DocumentBuilder ensureDocumentBuilder() {
        if (documentBuilder == null) {
            try {
                DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
                dbf.setNamespaceAware(true);
                documentBuilder = dbf.newDocumentBuilder();
            } catch (ParserConfigurationException e) {
                log.error("Error creating DocumentBuilder; " + e.getMessage());
            }
        }

        return documentBuilder;
    }

    public static String serializePretty(Document document) {
        try {
            Writer out = new StringWriter();
            serializePretty(document, out);
            return out.toString();
        } catch (IOException e) {
            log.error("Failed to serialize: " + e);
        }
        return null;
    }

    public static void serializePretty(Document dom, Writer writer) throws IOException {
        try {
            XmlObject xmlObject = XmlObject.Factory.parse(dom.getDocumentElement());
            serializePretty(xmlObject, writer);
        } catch (Exception e) {
            throw new IOException(e.toString());
        }
    }

    public static void serializePretty(XmlObject xmlObject, Writer writer) throws IOException {
        XmlOptions options = new XmlOptions();
        options.setSavePrettyPrint();
        options.setSavePrettyPrintIndent(3);
        options.setSaveNoXmlDecl();
        options.setSaveAggressiveNamespaces();
        // StringToStringMap map = new StringToStringMap();
        // map.put( SoapVersion.Soap11.getEnvelopeNamespace(), "SOAPENV" );
        // map.put( SoapVersion.Soap12.getEnvelopeNamespace(), "SOAPENV" );
        //
        // options.setSaveSuggestedPrefixes( map );

        xmlObject.save(writer, options);
    }

    public static XmlObject createXmlObject(InputStream input, XmlOptions xmlOptions) throws XmlException {
        try {
            return XmlObject.Factory.parse(input, xmlOptions);
        } catch (Exception e) {
            throw new XmlException(e.toString());
        }
    }

    public static XmlObject createXmlObject(String input, XmlOptions xmlOptions) throws XmlException {
        return XmlObject.Factory.parse(input, xmlOptions);
    }

    public static XmlObject createXmlObject(URL input, XmlOptions xmlOptions) throws XmlException {
        try {
            return XmlObject.Factory.parse(input, xmlOptions);
        } catch (Exception e) {
            throw new XmlException(e.toString());
        }
    }

    public static XmlObject createXmlObject(Node input, XmlOptions xmlOptions) throws XmlException {
        return XmlObject.Factory.parse(input, xmlOptions);
    }

    public static XmlObject createXmlObject(File input, XmlOptions xmlOptions) throws XmlException {
        try {
            return XmlObject.Factory.parse(input, xmlOptions);
        } catch (Exception e) {
            throw new XmlException(e.toString());
        }
    }

    public static XmlObject createXmlObject(InputStream input) throws XmlException {
        try {
            return XmlObject.Factory.parse(input);
        } catch (Exception e) {
            throw new XmlException(e.toString());
        }
    }

    public static XmlObject createXmlObject(String input) throws XmlException {
        return XmlObject.Factory.parse(input);
    }

    public static XmlObject createXmlObject(URL input) throws XmlException {
        try {
            return XmlObject.Factory.parse(input);
        } catch (Exception e) {
            // TODO e.toString() -> bad practice;
            throw new XmlException(e);
        }
    }

    public static XmlObject createXmlObject(Node input) throws XmlException {
        return XmlObject.Factory.parse(input);
    }

    public static XmlObject createXmlObject(File input) throws XmlException {
        try {
            return XmlObject.Factory.parse(input);
        } catch (Exception e) {
            throw new XmlException(e.toString());
        }
    }

    /**
     * XmlOptions configuration used in preventing XML Bomb
     * 
     * @return XmlOptions
     */
    public static XmlOptions createDefaultXmlOptions() {
        XmlOptions xmlOptions;

        try {
            SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
            SecurityManager securityManager = new SecurityManager();
            // Default seems to be 64000!
            // TODO
            // securityManager.setEntityExpansionLimit( 16 );

            saxParser.setProperty("http://apache.org/xml/properties/security-manager", securityManager);
            XMLReader xmlReader = saxParser.getXMLReader();
            xmlOptions = new XmlOptions().setLoadUseXMLReader(xmlReader);
        } catch (Exception e) {
            xmlOptions = new XmlOptions();
            log.error("Error creating XmlOptions; " + e.getMessage(), e);
        }
        return xmlOptions;
    }

    public static void serialize(Document dom, Writer writer) throws IOException {
        serialize(dom.getDocumentElement(), writer);
    }

    public static void serialize(Element elm, Writer writer) throws IOException {
        try {
            XmlObject xmlObject = XmlObject.Factory.parse(elm);
            xmlObject.save(writer);
        } catch (XmlException e) {
            throw new IOException(e.toString());
        }
    }

    static public String serialize(Node node, boolean prettyPrint) {
        try {
            XmlObject xmlObject = XmlObject.Factory.parse(node);
            return prettyPrint ? xmlObject.xmlText(new XmlOptions().setSavePrettyPrint()) : xmlObject.xmlText();
        } catch (XmlException e) {
            return e.toString();
        }
    }

    static public void setElementText(Element elm, String text) {
        Node node = elm.getFirstChild();
        if (node == null) {
            if (text != null)
                elm.appendChild(elm.getOwnerDocument().createTextNode(text));
        } else if (node.getNodeType() == Node.TEXT_NODE) {
            if (text == null)
                node.getParentNode().removeChild(node);
            else
                node.setNodeValue(text);
        } else if (text != null) {
            Text textNode = node.getOwnerDocument().createTextNode(text);
            elm.insertBefore(textNode, elm.getFirstChild());
        }
    }

    public static String getChildElementText(Element elm, String name) {
        Element child = getFirstChildElement(elm, name);
        return child == null ? null : getElementText(child);
    }

    public static Element getFirstChildElement(Element elm) {
        return getFirstChildElement(elm, null);
    }

    public static Element getFirstChildElement(Element elm, String name) {
        if (elm == null)
            return null;

        NodeList nl = elm.getChildNodes();
        for (int c = 0; c < nl.getLength(); c++) {
            Node node = nl.item(c);
            if (node.getNodeType() == Node.ELEMENT_NODE && (name == null || node.getNodeName().equals(name)))
                return (Element) node;
        }

        return null;
    }

    public static Element getFirstChildElementIgnoreCase(Element elm, String name) {
        if (elm == null)
            return null;

        NodeList nl = elm.getChildNodes();
        for (int c = 0; c < nl.getLength(); c++) {
            Node node = nl.item(c);
            if (node.getNodeType() == Node.ELEMENT_NODE
                    && (name == null || node.getNodeName().equalsIgnoreCase(name)))
                return (Element) node;
        }

        return null;
    }

    public static Element getFirstChildElementNS(Element elm, String tns, String localName) {
        if (tns == null && localName == null)
            return getFirstChildElement(elm);

        if (tns == null || tns.length() == 0)
            return getFirstChildElement(elm, localName);

        NodeList nl = elm.getChildNodes();
        for (int c = 0; c < nl.getLength(); c++) {
            Node node = nl.item(c);
            if (node.getNodeType() != Node.ELEMENT_NODE)
                continue;

            if (localName == null && tns.equals(node.getNamespaceURI()))
                return (Element) node;

            if (localName != null && tns.equals(node.getNamespaceURI()) && localName.equals(node.getLocalName()))
                return (Element) node;
        }

        return null;
    }

    static public String getElementText(Element elm) {
        Node node = elm.getFirstChild();
        if (node != null && node.getNodeType() == Node.TEXT_NODE)
            return node.getNodeValue();

        return null;
    }

    static public String getFragmentText(DocumentFragment elm) {
        Node node = elm.getFirstChild();
        if (node != null && node.getNodeType() == Node.TEXT_NODE)
            return node.getNodeValue();

        return null;
    }

    public static String getChildElementText(Element elm, String name, String defaultValue) {
        String result = getChildElementText(elm, name);
        return result == null ? defaultValue : result;
    }

    static public String getNodeValue(Node node) {
        if (node == null)
            return null;

        if (node.getNodeType() == Node.ELEMENT_NODE)
            return getElementText((Element) node);
        else if (node.getNodeType() == Node.DOCUMENT_FRAGMENT_NODE)
            return getFragmentText((DocumentFragment) node);
        else
            return node.getNodeValue();
    }

    public static Node createNodeFromPath(Element modelElement, String path) {
        Document document = modelElement.getOwnerDocument();
        StringTokenizer st = new StringTokenizer(path, "/");
        while (st.hasMoreTokens()) {
            String t = st.nextToken();

            if (st.hasMoreTokens()) {
                if (t.equals("..")) {
                    modelElement = (Element) modelElement.getParentNode();
                } else {
                    Element elm = getFirstChildElement(modelElement, t);
                    if (elm == null)
                        modelElement = (Element) modelElement.insertBefore(document.createElement(t),
                                getFirstChildElement(modelElement, t));
                    else
                        modelElement = elm;
                }
            } else {
                modelElement = (Element) modelElement.insertBefore(document.createElement(t),
                        getFirstChildElement(modelElement, t));
            }
        }

        return modelElement;
    }

    public static Element addChildElement(Element element, String name, String text) {
        Document document = element.getOwnerDocument();
        Element result = (Element) element.appendChild(document.createElement(name));
        if (text != null)
            result.appendChild(document.createTextNode(text));

        return result;
    }

    public static void setChildElementText(Element element, String name, String text) {
        Element elm = getFirstChildElement(element, name);
        if (elm == null) {
            elm = element.getOwnerDocument().createElement(name);
            element.appendChild(elm);
        }

        setElementText(elm, text);
    }

    public static Document parseXml(String xmlString) throws IOException {
        return parse(new InputSource(new StringReader(xmlString)));
    }

    public static void dumpParserErrors(XmlObject xmlObject) {
        List<?> errors = new ArrayList<Object>();
        xmlObject.validate(new XmlOptions().setErrorListener(errors));
        for (Iterator<?> i = errors.iterator(); i.hasNext();) {
            System.out.println(i.next());
        }
    }

    //   public static String transferValues( String source, String dest )
    //   {
    //      if( StringUtils.isBlank(source) || StringUtils.isBlank(dest) )
    //         return dest;
    //
    //      XmlCursor cursor = null;
    //      try
    //      {
    //         XmlObject sourceXml = XmlObject.Factory.parse( source );
    //         XmlObject destXml = XmlObject.Factory.parse( dest );
    //
    //         cursor = sourceXml.newCursor();
    //         cursor.toNextToken();
    //         while( !cursor.isEnddoc() )
    //         {
    //            while( !cursor.isContainer() && !cursor.isEnddoc() )
    //               cursor.toNextToken();
    //
    //            if( cursor.isContainer() )
    //            {
    //               Element elm = ( Element )cursor.getDomNode();
    //               String path = createXPath( elm );
    //               XmlObject[] paths = destXml.selectPath( path );
    //               if( paths != null && paths.length > 0 )
    //               {
    //                  Element elm2 = ( Element )paths[0].getDomNode();
    //
    //                  // transfer attributes
    //                  transferAttributes( elm, elm2 );
    //
    //                  // transfer text
    //                  setElementText( elm2, getElementText( elm ) );
    //
    //                  while( elm.getNextSibling() != null && elm2.getNextSibling() != null
    //                        && elm.getNextSibling().getNodeName().equals( elm.getNodeName() )
    //                        && !elm2.getNextSibling().getNodeName().equals( elm2.getNodeName() ) )
    //                  {
    //                     elm2 = ( Element )elm2.getParentNode().insertBefore(
    //                           elm2.getOwnerDocument().createElementNS( elm2.getNamespaceURI(), elm2.getLocalName() ),
    //                           elm2.getNextSibling() );
    //
    //                     elm = ( Element )elm.getNextSibling();
    //
    //                     // transfer attributes
    //                     transferAttributes( elm, elm2 );
    //
    //                     // transfer text
    //                     setElementText( elm2, getElementText( elm ) );
    //                  }
    //
    //               }
    //
    //               cursor.toNextToken();
    //            }
    //         }
    //
    //         return destXml.xmlText();
    //      }
    //      catch( Exception e )
    //      {
    //         e.printStackTrace();
    //      }
    //      finally
    //      {
    //         if( cursor != null )
    //            cursor.dispose();
    //      }
    //
    //      return dest;
    //   }

    private static void transferAttributes(Element elm, Element elm2) {
        NamedNodeMap attributes = elm.getAttributes();
        for (int c = 0; c < attributes.getLength(); c++) {
            Attr attr = (Attr) attributes.item(c);
            elm2.setAttributeNodeNS((Attr) elm2.getOwnerDocument().importNode(attr, true));
        }
    }

    /**
     * Returns absolute xpath for specified element, ignores namespaces
     * 
     * @param element
     *           the element to create for
     * @return the elements path in its containing document
     */

    public static String getElementPath(Element element) {
        Node elm = element;

        String result = elm.getNodeName() + "[" + getElementIndex(elm) + "]";
        while (elm.getParentNode() != null && elm.getParentNode().getNodeType() != Node.DOCUMENT_NODE) {
            elm = elm.getParentNode();
            result = elm.getNodeName() + "[" + getElementIndex(elm) + "]/" + result;
        }

        return "/" + result;
    }

    /**
     * Gets the index of the specified element amongst elements with the same
     * name
     * 
     * @param element
     *           the element to get for
     * @return the index of the element, will be >= 1
     */

    public static int getElementIndex(Node element) {
        int result = 1;

        Node elm = element.getPreviousSibling();
        while (elm != null) {
            if (elm.getNodeType() == Node.ELEMENT_NODE && elm.getNodeName().equals(element.getNodeName()))
                result++;
            elm = elm.getPreviousSibling();
        }

        return result;
    }

    public static String declareXPathNamespaces(String xmlString) throws XmlException {
        return declareXPathNamespaces(XmlObject.Factory.parse(xmlString));
    }

    public static synchronized String prettyPrintXml(String xml) {
        try {
            if (!XmlUtils.seemsToBeXml(xml))
                return xml;

            StringWriter writer = new StringWriter();
            XmlUtils.serializePretty(XmlObject.Factory.parse(xml), writer);
            return writer.toString();
        } catch (Exception e) {
            log.warn("Failed to prettyPrint xml [" + xml + "]: " + e);
            return xml;
        }
    }

    public static synchronized String prettyPrintXml(XmlObject xml) {
        try {
            if (xml == null)
                return null;

            StringWriter writer = new StringWriter();
            XmlUtils.serializePretty(xml, writer);
            return writer.toString();
        } catch (Exception e) {
            log.warn("Failed to prettyPrint xml [" + xml + "]: " + e);
            return xml.xmlText();
        }
    }

    //   public static String declareXPathNamespaces( WsdlInterface iface )
    //   {
    //      StringBuffer buf = new StringBuffer();
    //      buf.append( "declare namespace test='" );
    //      buf.append( iface.getSoapVersion().getEnvelopeNamespace() );
    //      buf.append( "';\n" );
    //
    //      try
    //      {
    //         Collection<String> namespaces = iface.getWsdlContext().getInterfaceDefinition().getDefinedNamespaces();
    //         int c = 1;
    //         for( Iterator<String> i = namespaces.iterator(); i.hasNext(); )
    //         {
    //            buf.append( "declare namespace ns" );
    //            buf.append( c++ );
    //            buf.append( "='" );
    //            buf.append( i.next() );
    //            buf.append( "';\n" );
    //         }
    //      }
    //      catch( Exception e )
    //      {
    //         e.printStackTrace();
    //      }
    //
    //      return buf.toString();
    //   }

    //   public static String createXPath( Node node )
    //   {
    //      return createXPath( node, false, false, false, null );
    //   }
    //
    //   public static String createAbsoluteXPath( Node node )
    //   {
    //      return createXPath( node, false, false, true, null );
    //   }
    //
    //   public static String createXPath( Node node, boolean anonymous, boolean selectText, XPathModifier modifier )
    //   {
    //      return createXPath( node, anonymous, selectText, false, modifier );
    //   }

    //   public static String createXPath( Node node, boolean anonymous, boolean selectText, boolean absolute,
    //         XPathModifier modifier )
    //   {
    //      XPathData xpathData = createXPathData( node, anonymous, selectText, absolute );
    //      if( xpathData == null )
    //         return null;
    //      return xpathData.buildXPath( modifier );
    //   }
    //
    //   public static XPathData createXPathData( Node node, boolean anonymous, boolean selectText, boolean absolute )
    //   {
    //      StringToStringMap nsMap = new StringToStringMap();
    //      List<String> pathComponents = new ArrayList<String>();
    //
    //      int nsCnt = 1;
    //
    //      String namespaceURI = node.getNamespaceURI();
    //      // if( node.getNodeType() == Node.TEXT_NODE )
    //      // {
    //      // node = node.getParentNode();
    //      // }
    //      if( node.getNodeType() == Node.ATTRIBUTE_NODE )
    //      {
    //         if( namespaceURI != null && namespaceURI.length() > 0 )
    //         {
    //            String prefix = node.getPrefix();
    //            if( prefix == null || prefix.length() == 0 )
    //               prefix = "ns" + nsCnt++ ;
    //
    //            nsMap.put( namespaceURI, prefix );
    //            pathComponents.add( "@" + prefix + ":" + node.getLocalName() );
    //         }
    //         else
    //         {
    //            pathComponents.add( "@" + node.getLocalName() );
    //         }
    //         node = ( ( Attr )node ).getOwnerElement();
    //      }
    //      else if( node.getNodeType() == Node.DOCUMENT_NODE )
    //      {
    //         node = ( ( Document )node ).getDocumentElement();
    //      }
    //      // else if( node.getNodeType() == Node.DOCUMENT_FRAGMENT_NODE )
    //      // {
    //      // node =
    //      // ((DocumentFragment)node).getOwnerDocument().getDocumentElement();
    //      // }
    //
    //      if( node.getNodeType() == Node.ELEMENT_NODE )
    //      {
    //         int index = anonymous ? 0 : findNodeIndex( node );
    //
    //         String pc = null;
    //
    //         namespaceURI = node.getNamespaceURI();
    //         if( namespaceURI != null && namespaceURI.length() > 0 )
    //         {
    //            String prefix = node.getPrefix();
    //            if( prefix == null || prefix.length() == 0 )
    //               prefix = "ns" + nsCnt++ ;
    //
    //            while( !nsMap.containsKey( namespaceURI ) && nsMap.containsValue( prefix ) )
    //            {
    //               prefix = "ns" + nsCnt++ ;
    //            }
    //
    //            nsMap.put( namespaceURI, prefix );
    //            pc = prefix + ":" + node.getLocalName();
    //         }
    //         else
    //         {
    //            pc = node.getLocalName();
    //         }
    //
    //         String elementText = XmlUtils.getElementText( ( Element )node );
    //
    //         // not an attribute?
    //         if( selectText && pathComponents.isEmpty() && elementText != null && elementText.trim().length() > 0 )
    //            pathComponents.add( "text()" );
    //
    //         pathComponents.add( pc + ( ( index == 0 ) ? "" : "[" + index + "]" ) );
    //      }
    //      else
    //         return null;
    //
    //      node = node.getParentNode();
    //      namespaceURI = node.getNamespaceURI();
    //      while( node != null
    //            && node.getNodeType() == Node.ELEMENT_NODE
    //            && ( absolute || ( !"Body".equals( node.getNodeName() )
    //                  && !SoapVersion.Soap11.getEnvelopeNamespace().equals( namespaceURI ) && !SoapVersion.Soap12
    //                  .getEnvelopeNamespace().equals( namespaceURI ) ) ) )
    //      {
    //         int index = anonymous ? 0 : findNodeIndex( node );
    //
    //         String ns = nsMap.get( namespaceURI );
    //         String pc = null;
    //
    //         if( ns == null && namespaceURI != null && namespaceURI.length() > 0 )
    //         {
    //            String prefix = node.getPrefix();
    //            if( prefix == null || prefix.length() == 0 )
    //               prefix = "ns" + nsCnt++ ;
    //
    //            while( !nsMap.containsKey( namespaceURI ) && nsMap.containsValue( prefix ) )
    //            {
    //               prefix = "ns" + nsCnt++ ;
    //            }
    //
    //            nsMap.put( namespaceURI, prefix );
    //            ns = nsMap.get( namespaceURI );
    //
    //            pc = prefix + ":" + node.getLocalName();
    //         }
    //         else if( ns != null )
    //         {
    //            pc = ns + ":" + node.getLocalName();
    //         }
    //         else
    //         {
    //            pc = node.getLocalName();
    //         }
    //
    //         pathComponents.add( pc + ( ( index == 0 ) ? "" : "[" + index + "]" ) );
    //         node = node.getParentNode();
    //         namespaceURI = node.getNamespaceURI();
    //      }
    //
    //      return new XPathData( nsMap, pathComponents, absolute );
    //   }

    private static int findNodeIndex(Node node) {
        String nm = node.getLocalName();
        String ns = node.getNamespaceURI();
        short nt = node.getNodeType();

        Node parentNode = node.getParentNode();
        if (parentNode.getNodeType() != Node.ELEMENT_NODE)
            return 1;

        Node child = parentNode.getFirstChild();

        int ix = 0;
        while (child != null) {
            if (child == node)
                return ix + 1;

            if (child.getNodeType() == nt && nm.equals(child.getLocalName())
                    && ((ns == null && child.getNamespaceURI() == null)
                            || (ns != null && ns.equals(child.getNamespaceURI()))))
                ix++;

            child = child.getNextSibling();
        }

        throw new SoapBuilderException("Child node not found in parent!?");
    }

    public static boolean setNodeValue(Node domNode, String string) {
        if (domNode == null)
            return false;

        short nodeType = domNode.getNodeType();

        switch (nodeType) {
        case Node.ELEMENT_NODE: {
            setElementText((Element) domNode, string);
            break;
        }
        case Node.ATTRIBUTE_NODE:
        case Node.TEXT_NODE: {
            domNode.setNodeValue(string);
            break;
        }
        case Node.PROCESSING_INSTRUCTION_NODE: {
            ((ProcessingInstruction) domNode).setData(string);
            break;
        }
        case Node.CDATA_SECTION_NODE: {
            ((CDATASection) domNode).setData(string);
            break;
        }
        default: {
            return false;
        }
        }

        return true;
    }

    public static String declareXPathNamespaces(XmlObject xmlObject) {
        Map<QName, String> map = new HashMap<QName, String>();
        XmlCursor cursor = xmlObject.newCursor();

        while (cursor.hasNextToken()) {
            if (cursor.toNextToken().isNamespace())
                map.put(cursor.getName(), cursor.getTextValue());
        }

        cursor.dispose();

        Iterator<QName> i = map.keySet().iterator();
        int nsCnt = 0;

        StringBuffer buf = new StringBuffer();
        Set<String> prefixes = new HashSet<String>();
        Set<String> usedPrefixes = new HashSet<String>();

        while (i.hasNext()) {
            QName name = i.next();
            String prefix = name.getLocalPart();
            if (prefix.length() == 0)
                prefix = "ns" + Integer.toString(++nsCnt);
            else if (prefix.equals("xsd") || prefix.equals("xsi"))
                continue;

            if (usedPrefixes.contains(prefix)) {
                int c = 1;
                while (usedPrefixes.contains(prefix + c))
                    c++;

                prefix = prefix + Integer.toString(c);
            } else
                prefixes.add(prefix);

            buf.append("declare namespace ");
            buf.append(prefix);
            buf.append("='");
            buf.append(map.get(name));
            buf.append("';\n");

            usedPrefixes.add(prefix);
        }

        return buf.toString();
    }

    public static String setXPathContent(String xmlText, String xpath, String value) {
        try {
            XmlObject xmlObject = XmlObject.Factory.parse(xmlText);

            String namespaces = declareXPathNamespaces(xmlObject);
            if (namespaces != null && namespaces.trim().length() > 0)
                xpath = namespaces + xpath;

            XmlObject[] path = xmlObject.selectPath(xpath);
            for (XmlObject xml : path) {
                setNodeValue(xml.getDomNode(), value);
            }

            return xmlObject.toString();
        } catch (Exception e) {
            // TODO
            e.printStackTrace();
        }

        return xmlText;
    }

    public static QName getQName(Node node) {
        if (node == null)
            return null;
        else if (node.getNamespaceURI() == null)
            return new QName(node.getNodeName());
        else
            return new QName(node.getNamespaceURI(), node.getLocalName());
    }

    public static String removeXPathNamespaceDeclarations(String xpath) {
        while (xpath.startsWith("declare namespace")) {
            int ix = xpath.indexOf(';');
            if (ix == -1)
                break;

            xpath = xpath.substring(ix + 1).trim();
        }
        return xpath;
    }

    public static String stripWhitespaces(String content) {
        try {
            XmlObject xml = XmlObject.Factory.parse(content,
                    new XmlOptions().setLoadStripWhitespace().setLoadStripComments());
            content = xml.xmlText();
        } catch (Exception e) {
            // TODO
            e.printStackTrace();
        }

        return content;
    }

    public static NodeList getChildElements(Element elm) {
        List<Element> list = new ArrayList<Element>();

        NodeList nl = elm.getChildNodes();
        for (int c = 0; c < nl.getLength(); c++) {
            Node item = nl.item(c);
            if (item.getParentNode() == elm && item.getNodeType() == Node.ELEMENT_NODE)
                list.add((Element) item);
        }

        return new ElementNodeList(list);
    }

    public static NodeList getChildElementsByTagName(Element elm, String name) {
        List<Element> list = new ArrayList<Element>();

        NodeList nl = elm.getChildNodes();
        for (int c = 0; c < nl.getLength(); c++) {
            Node item = nl.item(c);
            if (item.getParentNode() == elm && item.getNodeType() == Node.ELEMENT_NODE
                    && name.equals(item.getNodeName()))
                list.add((Element) item);
        }

        return new ElementNodeList(list);
    }

    public static NodeList getChildElementsOfType(Element elm, SchemaType schemaType) {
        List<Element> list = new ArrayList<Element>();

        NodeList nl = elm.getChildNodes();
        for (int c = 0; c < nl.getLength(); c++) {
            Node item = nl.item(c);
            if (item.getParentNode() == elm && item.getNodeType() == Node.ELEMENT_NODE && ((Element) item)
                    .getAttributeNS(Constants.XSI_NS, "type").endsWith(":" + schemaType.getName().getLocalPart())) {
                list.add((Element) item);
            }
        }

        return new ElementNodeList(list);
    }

    public static NodeList getChildElementsNS(Element elm, QName name) {
        return getChildElementsByTagNameNS(elm, name.getNamespaceURI(), name.getLocalPart());
    }

    public static NodeList getChildElementsByTagNameNS(Element elm, String namespaceUri, String localName) {
        List<Element> list = new ArrayList<Element>();

        NodeList nl = elm.getChildNodes();
        for (int c = 0; c < nl.getLength(); c++) {
            Node item = nl.item(c);
            if (item.getParentNode() == elm && item.getNodeType() == Node.ELEMENT_NODE
                    && localName.equals(item.getLocalName()) && namespaceUri.equals(item.getNamespaceURI()))
                list.add((Element) item);
        }

        return new ElementNodeList(list);
    }

    public static String serialize(Document document) {
        StringWriter writer = new StringWriter();
        try {
            serialize(document, writer);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return writer.toString();
    }

    public static Element getFirstChildElementNS(Element domNode, QName name) {
        return getFirstChildElementNS(domNode, name.getNamespaceURI(), name.getLocalPart());
    }

    public static QName findTypeNameForXsiType(String typeName, Element elm) {
        int ix = typeName.indexOf(':');
        if (ix == -1)
            return null;

        String prefix = typeName.substring(0, ix);
        String localName = typeName.substring(ix + 1);
        String namespaceUri = elm.getAttribute("xmlns:" + prefix);

        if (!StringUtils.isNotBlank(namespaceUri))
            namespaceUri = findNamespaceForPrefix(elm, prefix);

        if (StringUtils.isNotBlank(namespaceUri)) {
            return new QName(namespaceUri, localName);
        }

        return null;
    }

    private static String findNamespaceForPrefix(Element elm, String prefix) {
        String namespaceUri = null;
        while (StringUtils.isBlank(namespaceUri) && elm != null) {
            if (elm.getParentNode().getNodeType() != Node.ELEMENT_NODE)
                break;

            elm = (Element) elm.getParentNode();
            namespaceUri = elm.getAttribute("xmlns:" + prefix);
        }

        return StringUtils.isBlank(namespaceUri) ? null : namespaceUri;
    }

    public static String findPrefixForNamespace(Element elm, String namespace) {
        while (elm != null) {
            NamedNodeMap attributes = elm.getAttributes();
            for (int c = 0; c < attributes.getLength(); c++) {
                if (attributes.item(c).getNodeValue().equals(namespace)
                        && attributes.item(c).getNodeName().startsWith("xmlns:")) {
                    return attributes.item(c).getNodeName().substring(6);
                }
            }

            if (elm.getParentNode().getNodeType() != Node.ELEMENT_NODE)
                break;

            elm = (Element) elm.getParentNode();
        }

        return null;
    }

    public static void setXsiType(Element elm, QName name) {
        String prefix = findPrefixForNamespace(elm, name.getNamespaceURI());
        if (prefix == null) {
            prefix = generatePrefixForNamespace(name.getNamespaceURI());
            while (findNamespaceForPrefix(elm, prefix) != null) {
                prefix = generatePrefixForNamespace(name.getNamespaceURI());
            }

            elm.setAttribute("xmlns:" + prefix, name.getNamespaceURI());
        }

        elm.setAttributeNS(Constants.XSI_NS, "type", prefix + ":" + name.getLocalPart());
    }

    private static String generatePrefixForNamespace(String namespaceURI) {
        return "ns" + (int) (Math.random() * 1000);
    }

    public static QName createQName(Node node) {
        return new QName(node.getNamespaceURI(), node.getLocalName());
    }

    public static Node getNextElementSibling(Node node) {
        node = node.getNextSibling();
        while (node != null && node.getNodeType() != Node.ELEMENT_NODE) {
            node = node.getNextSibling();
        }

        return node;
    }

    public static Document createDocument(QName element) {
        ensureDocumentBuilder();

        Document document = documentBuilder.newDocument();
        document.appendChild(document.createElementNS(element.getNamespaceURI(), element.getLocalPart()));
        return document;
    }

    public static String getValueForMatch(XmlCursor cursor) {
        Node domNode = cursor.getDomNode();
        String stringValue;

        if (domNode.getNodeType() == Node.ATTRIBUTE_NODE || domNode.getNodeType() == Node.TEXT_NODE) {
            stringValue = domNode.getNodeValue();
        } else if (cursor.getObject() instanceof XmlAnySimpleType) {
            stringValue = ((XmlAnySimpleType) cursor.getObject()).getStringValue();
        } else {
            if (domNode.getNodeType() == Node.ELEMENT_NODE) {
                Element elm = (Element) domNode;
                if (elm.getChildNodes().getLength() == 1 && !hasContentAttributes(elm)) {
                    stringValue = getElementText(elm);
                } else {
                    stringValue = cursor.getObject().xmlText(
                            new XmlOptions().setSavePrettyPrint().setSaveOuter().setSaveAggressiveNamespaces());
                }
            } else {
                stringValue = domNode.getNodeValue();
            }
        }
        return stringValue;
    }

    public static boolean hasContentAttributes(Element elm) {
        NamedNodeMap attributes = elm.getAttributes();
        for (int c = 0; c < attributes.getLength(); c++) {
            Node item = attributes.item(c);
            String ns = item.getNamespaceURI();
            if (!ns.equals(Constants.XML_NS)
            // && !ns.equals( Constants.XSI_NS ) && !ns.equals(
            // Constants.XSI_NS_2000 )
            // && !ns.equals( Constants.XSD_NS )
            )
                return true;
        }

        return false;
    }

    public static String getValueForMatch(Node domNode, boolean prettyPrintXml) {
        String stringValue;

        if (domNode.getNodeType() == Node.ATTRIBUTE_NODE || domNode.getNodeType() == Node.TEXT_NODE) {
            stringValue = domNode.getNodeValue();
        } else {
            if (domNode.getNodeType() == Node.ELEMENT_NODE) {
                Element elm = (Element) domNode;
                if (elm.getChildNodes().getLength() == 1 && !hasContentAttributes(elm)) {
                    stringValue = getElementText(elm);
                } else {
                    stringValue = XmlUtils.serialize(domNode, prettyPrintXml);
                }
            } else {
                stringValue = domNode.getNodeValue();
            }
        }

        return stringValue;
    }

    public static String selectFirstNodeValue(XmlObject xmlObject, String xpath) throws XmlException {
        Node domNode = selectFirstDomNode(xmlObject, xpath);
        return domNode == null ? null : getNodeValue(domNode);
    }

    public static String[] selectNodeValues(XmlObject xmlObject, String xpath) {
        Node[] nodes = selectDomNodes(xmlObject, xpath);

        String[] result = new String[nodes.length];
        for (int c = 0; c < nodes.length; c++) {
            result[c] = getNodeValue(nodes[c]);
        }

        return result;
    }

    public static Node selectFirstDomNode(XmlObject xmlObject, String xpath) {
        XmlCursor cursor = xmlObject.newCursor();
        try {
            cursor.selectPath(xpath);

            if (cursor.toNextSelection()) {
                return cursor.getDomNode();
            } else
                return null;
        } finally {
            cursor.dispose();
        }
    }

    public static Node[] selectDomNodes(XmlObject xmlObject, String xpath) {
        List<Node> result = new ArrayList<Node>();

        XmlCursor cursor = xmlObject.newCursor();
        try {
            cursor.selectPath(xpath);

            while (cursor.toNextSelection()) {
                result.add(cursor.getDomNode());
            }
        } finally {
            cursor.dispose();
        }

        return result.toArray(new Node[result.size()]);
    }

    private final static class ElementNodeList implements NodeList {
        private final List<Element> list;

        public ElementNodeList(List<Element> list) {
            this.list = list;
        }

        public int getLength() {
            return list.size();
        }

        public Node item(int index) {
            return list.get(index);
        }
    }

    public static boolean seemsToBeXml(String str) {
        try {
            if (StringUtils.isBlank(str))
                return false;

            XmlObject.Factory.parse(str);

            // SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
            // saxParserFactory.setNamespaceAware( true );
            // saxParserFactory.setValidating( false );
            // saxParserFactory.setFeature( XMLConstants.FEATURE_SECURE_PROCESSING,
            // true );
            // SAXParser p = saxParserFactory.newSAXParser();
            // p.parse( new StringInputStream( str ), new HandlerBase()
            // {
            //
            // @Override
            // public InputSource resolveEntity( String arg0, String arg1 ) throws
            // SAXException
            // {
            // return null;
            // }
            // } );
            return true;
        } catch (Throwable e) {
            return false;
        }
    }

    public static String extractNamespaces(String xpath) {
        String result = xpath;
        int ix = xpath.lastIndexOf("declare namespace");
        if (ix != -1) {
            ix = xpath.indexOf('\'', ix + 1);
            if (ix != -1) {
                ix = xpath.indexOf('\'', ix + 1);
                if (ix != -1) {
                    ix = xpath.indexOf(';');
                    if (ix != -1) {
                        result = xpath.substring(0, ix + 1);
                    }
                }
            }
        } else {
            result = "";
        }

        return result;
    }

    public static String removeUnneccessaryNamespaces(String xml) {
        if (StringUtils.isBlank(xml))
            return xml;

        XmlObject xmlObject = null;
        XmlCursor cursor = null;
        try {
            xmlObject = XmlObject.Factory.parse(xml);

            cursor = xmlObject.newCursor();
            while (cursor.currentTokenType() != TokenType.START && cursor.currentTokenType() != TokenType.ENDDOC) {
                cursor.toNextToken();
            }

            if (cursor.currentTokenType() == TokenType.START) {
                Map<?, ?> nsMap = new HashMap<Object, Object>();

                cursor.getAllNamespaces(nsMap);
                nsMap.remove(cursor.getDomNode().getPrefix());

                NamedNodeMap attributes = cursor.getDomNode().getAttributes();
                for (int c = 0; attributes != null && c < attributes.getLength(); c++) {
                    nsMap.remove(attributes.item(c).getPrefix());
                }

                if (cursor.toFirstChild()) {
                    while (cursor.getDomNode() != xmlObject.getDomNode()) {
                        attributes = cursor.getDomNode().getAttributes();
                        for (int c = 0; attributes != null && c < attributes.getLength(); c++) {
                            nsMap.remove(attributes.item(c).getPrefix());
                        }

                        nsMap.remove(cursor.getDomNode().getPrefix());
                        cursor.toNextToken();
                    }
                }

                xml = xmlObject.xmlText(
                        new XmlOptions().setSaveOuter().setSavePrettyPrint().setSaveImplicitNamespaces(nsMap));
            }
        } catch (XmlException e) {

        } finally {
            if (cursor != null)
                cursor.dispose();
        }

        return xml;
    }

    public static String replaceNameInPathOrQuery(String pathOrQuery, String oldName, String newName)
            throws Exception {
        Tokenizer t = new Tokenizer();
        t.tokenize(pathOrQuery, 0, -1, 1);
        StringBuffer result = new StringBuffer();
        int lastIx = 0;

        while (t.currentToken != Token.EOF) {
            if (t.currentToken == Token.NAME && t.currentTokenValue.equals(oldName)) {
                result.append(pathOrQuery.substring(lastIx, t.currentTokenStartOffset));
                result.append(newName);
                lastIx = t.currentTokenStartOffset + t.currentTokenValue.length();
            }

            t.next();
        }

        if (lastIx < pathOrQuery.length())
            result.append(pathOrQuery.substring(lastIx));
        //
        System.out.println("returning " + result.toString());
        return result.toString();
    }

    public static QName getQName(XmlObject contentElement) {
        return contentElement == null ? null : getQName(contentElement.getDomNode());
    }

    public static String getXPathValue(String value, String xpath) {
        try {
            XmlObject xmlObject = XmlObject.Factory.parse(value);
            XmlObject[] nodes = xmlObject.selectPath(xpath);
            if (nodes.length > 0)
                return getNodeValue(nodes[0].getDomNode());
        } catch (XmlException e) {
            e.printStackTrace();
        }

        return null;
    }

    public static String createJdbcXmlResult(Statement statement)
            throws SQLException, ParserConfigurationException {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document xmlDocumentResult = builder.newDocument();
        Element resultsElement = xmlDocumentResult.createElement("Results");
        xmlDocumentResult.appendChild(resultsElement);

        if (statement != null) {
            ResultSet resultSet = statement.getResultSet();
            if (resultSet != null) {
                resultSet.setFetchSize(statement.getFetchSize());
                xmlDocumentResult = addResultSetXmlPart(resultsElement, resultSet, xmlDocumentResult);
                while (statement.getMoreResults()) {
                    xmlDocumentResult = addResultSetXmlPart(resultsElement, statement.getResultSet(),
                            xmlDocumentResult);
                }
            } else {
                Element errorElement = xmlDocumentResult.createElement("UpdateCount");
                errorElement
                        .appendChild(xmlDocumentResult.createTextNode(String.valueOf(statement.getUpdateCount())));
                resultsElement.appendChild(errorElement);
            }
        }

        StringWriter out = new StringWriter();

        OutputFormat outputFormat = new OutputFormat(xmlDocumentResult);
        outputFormat.setOmitComments(true);
        outputFormat.setOmitDocumentType(true);
        outputFormat.setOmitXMLDeclaration(true);
        // outputFormat.setLineSeparator( "\n" );
        // add this line //
        // outputFormat.setPreserveSpace( true );
        outputFormat.setIndent(3);
        outputFormat.setIndenting(true);

        try {
            XMLSerializer serializer = new XMLSerializer(new PrintWriter(out), outputFormat);
            serializer.asDOMSerializer();
            serializer.serialize(xmlDocumentResult);
        } catch (IOException e) {
            throw new SoapBuilderException(e);
        }

        return out.toString();
    }

    public static Document addResultSetXmlPart(Element resultsElement, ResultSet rs, Document xmlDocumentResult)
            throws SQLException {
        // resultSet = statement.getResultSet();
        // connection to an ACCESS MDB
        ResultSetMetaData rsmd = rs.getMetaData();
        Element resultSetElement = xmlDocumentResult.createElement("ResultSet");

        resultSetElement.setAttribute("fetchSize", String.valueOf(rs.getFetchSize()));
        resultsElement.appendChild(resultSetElement);

        int colCount = rsmd.getColumnCount();
        while (rs.next()) {
            Element rowElement = xmlDocumentResult.createElement("Row");
            rowElement.setAttribute("rowNumber", String.valueOf(rs.getRow()));

            resultsElement.appendChild(rowElement);
            for (int ii = 1; ii <= colCount; ii++) {
                String columnName = "";
                if (!StringUtils.isBlank(rsmd.getTableName(ii))) {
                    columnName += (rsmd.getTableName(ii)).toUpperCase() + ".";
                }
                columnName += (rsmd.getColumnName(ii)).toUpperCase();
                String value = rs.getString(ii);
                Element node = xmlDocumentResult.createElement(createXmlName(columnName));
                if (!StringUtils.isBlank(value)) {
                    Text textNode = xmlDocumentResult.createTextNode(value.toString());
                    node.appendChild(textNode);
                }
                rowElement.appendChild(node);
            }
            resultSetElement.appendChild(rowElement);
        }
        return xmlDocumentResult;
    }

    public static String createXmlName(String str) {
        StringBuffer result = new StringBuffer();
        boolean skipped = false;
        boolean numbersOnly = true;

        for (int c = 0; c < str.length(); c++) {
            char ch = str.charAt(c);

            if (Character.isLetter(ch) || ch == '_' || ch == '-' || ch == '.') {
                if (skipped)
                    result.append(Character.toUpperCase(ch));
                else
                    result.append(ch);
                numbersOnly = false;
                skipped = false;
            } else if (Character.isDigit(ch)) {
                result.append(ch);
                skipped = false;
            } else {
                skipped = true;
            }
        }

        str = result.toString();
        if (numbersOnly && str.length() > 0)
            str = "_" + str;

        return str;
    }

    // created by centeractive ag
    public static Source xmlStringToSource(String xmlString) {
        StringReader reader = new StringReader(xmlString);
        InputSource src = new InputSource(reader);
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        try {
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document dom = db.parse(src);
            Source xmlSource = new javax.xml.transform.dom.DOMSource(dom);
            return xmlSource;
        } catch (ParserConfigurationException ex) {
            throw new SoapBuilderException(ex);
        } catch (SAXException ex) {
            throw new SoapBuilderException(ex);
        } catch (IOException ex) {
            throw new SoapBuilderException(ex);
        }
    }

    // created by centeractive ag
    public static String sourceToXmlString(Source xmlSource) {
        if (xmlSource == null) {
            return "";
        }
        TransformerFactory factory = TransformerFactory.newInstance();
        Transformer transformer = null;
        try {
            transformer = factory.newTransformer();
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            StringWriter writer = new StringWriter();
            transformer.transform(xmlSource, new StreamResult(writer));
            return writer.toString();
        } catch (TransformerConfigurationException e) {
            throw new SoapBuilderException("Error during XML transformer configuration", e);
        } catch (TransformerException e) {
            throw new SoapBuilderException("Error during XML source transformation", e);
        }
    }

}