/*
* SoapUI, Copyright (C) 2004-2016 SmartBear Software
*
* Licensed under the EUPL, Version 1.1 or - as soon as they will be approved by the European Commission - subsequent
* versions of the EUPL (the "Licence");
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
*
* http://ec.europa.eu/idabc/eupl
*
* Unless required by applicable law or agreed to in writing, software distributed under the Licence is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the Licence for the specific language governing permissions and limitations
* under the Licence.
*/
package com.eviware.soapui.support.xml;
import com.eviware.soapui.SoapUI;
import com.eviware.soapui.impl.wsdl.WsdlInterface;
import com.eviware.soapui.impl.wsdl.support.Constants;
import com.eviware.soapui.impl.wsdl.support.soap.SoapVersion;
import com.eviware.soapui.support.StringUtils;
import com.eviware.soapui.support.types.StringToStringMap;
import net.sf.saxon.expr.Token;
import net.sf.saxon.expr.Tokenizer;
import org.apache.log4j.Logger;
import org.apache.xerces.util.SecurityManager;
import org.apache.xml.serialize.OutputFormat;
import org.apache.xml.serialize.XMLSerializer;
import org.apache.xmlbeans.SchemaType;
import org.apache.xmlbeans.XmlAnySimpleType;
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlCursor.TokenType;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions;
import org.w3c.dom.Attr;
import org.w3c.dom.CDATASection;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentFragment;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.ProcessingInstruction;
import org.w3c.dom.Text;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.net.URL;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
/**
* 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("&", "&").replaceAll("<", "<").replaceAll(">", ">")
.replaceAll("\"", """).replaceAll("'", "'");
}
public static String entitizeContent(String xml) {
return xml.replaceAll("&", "&").replaceAll("\"", """).replaceAll("'", "'");
}
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) {
throw new XmlException(e.toString());
}
}
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!
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 String transferValues(String source, String dest) {
if (StringUtils.isNullOrEmpty(source) || StringUtils.isNullOrEmpty(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) {
SoapUI.logError(e);
} 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) {
if (xml == null) {
return null;
}
try {
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) {
StringBuilder buf = new StringBuilder();
buf.append("declare namespace soap='");
buf.append(iface.getSoapVersion().getEnvelopeNamespace());
buf.append("';\n");
try {
Collection<String> namespaces = iface.getWsdlContext().getInterfaceDefinition().getDefinedNamespaces();
int c = 1;
for (String namespace : namespaces) {
buf.append("declare namespace ns");
buf.append(c++);
buf.append("='");
buf.append(namespace);
buf.append("';\n");
}
} catch (Exception e) {
SoapUI.logError(e);
}
return buf.toString();
}
public static String createXPath(Node domNode, boolean normalize) {
return createXPath(domNode, false, false, false, null, normalize);
}
public static String createXPath(Node node) {
return createXPath(node, false);
}
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) {
return createXPath(node, anonymous, selectText, absolute, modifier, false);
}
public static String createXPath(Node node, boolean anonymous, boolean selectText, boolean absolute,
XPathModifier modifier, boolean normalize) {
XPathData xpathData = createXPathData(node, anonymous, selectText, absolute, normalize);
if (xpathData == null) {
return null;
}
return xpathData.buildXPath(modifier);
}
public static XPathData createXPathData(Node node, boolean anonymous, boolean selectText, boolean absolute) {
return createXPathData(node, anonymous, selectText, absolute, false);
}
public static XPathData createXPathData(Node node, boolean anonymous, boolean selectText, boolean absolute,
boolean normalize) {
StringToStringMap nsMap = new StringToStringMap();
List<String> pathComponents = new ArrayList<String>();
int nsCnt = 1;
String namespaceURI = node.getNamespaceURI();
if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
if (namespaceURI != null && namespaceURI.length() > 0) {
String prefix = node.getPrefix();
if (normalize || 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();
}
if (node.getNodeType() == Node.ELEMENT_NODE) {
int index = anonymous ? 0 : findNodeIndex(node);
String pc;
namespaceURI = node.getNamespaceURI();
if (namespaceURI != null && namespaceURI.length() > 0) {
String prefix = node.getPrefix();
if (nsMap.containsKey(namespaceURI)) {
prefix = nsMap.get(namespaceURI);
} else {
if (normalize || 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;
if (ns == null && namespaceURI != null && namespaceURI.length() > 0) {
String prefix = node.getPrefix();
if (normalize || 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 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 RuntimeException("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();
int nsCnt = 0;
StringBuilder buf = new StringBuilder();
Set<String> prefixes = new HashSet<String>();
Set<String> usedPrefixes = new HashSet<String>();
for (Map.Entry<QName, String> entry : map.entrySet()) {
QName name = entry.getKey();
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(entry.getValue());
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) {
SoapUI.logError(e);
}
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) {
SoapUI.logError(e);
}
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.hasContent(namespaceUri)) {
namespaceUri = findNamespaceForPrefix(elm, prefix);
}
if (StringUtils.hasContent(namespaceUri)) {
return new QName(namespaceUri, localName);
}
return null;
}
private static String findNamespaceForPrefix(Element elm, String prefix) {
String namespaceUri = null;
while (StringUtils.isNullOrEmpty(namespaceUri) && elm != null) {
if (elm.getParentNode().getNodeType() != Node.ELEMENT_NODE) {
break;
}
elm = (Element) elm.getParentNode();
namespaceUri = elm.getAttribute("xmlns:" + prefix);
}
return StringUtils.isNullOrEmpty(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.isNullOrEmpty(str)) {
return false;
}
XmlObject.Factory.parse(str);
return true;
} catch (Exception 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.isNullOrEmpty(xml)) {
return xml;
}
XmlObject xmlObject;
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 (Throwable e) {
e.printStackTrace();
}
return null;
}
public static String createJdbcXmlResult(Statement statement) throws SQLException, ParserConfigurationException {
return createJdbcXmlResultEx(statement, true);
}
public static String createJdbcXmlResultEx(Statement statement, boolean makeUpperCased) throws SQLException, ParserConfigurationException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
org.w3c.dom.Document xmlDocumentResult = builder.newDocument();
Element resultsElement = xmlDocumentResult.createElement("Results");
xmlDocumentResult.appendChild(resultsElement);
if (statement != null) {
try (ResultSet resultSet = statement.getResultSet()) {
if (resultSet != null) {
resultSet.setFetchSize(statement.getFetchSize());
xmlDocumentResult = addResultSetXmlPart(resultsElement, resultSet, xmlDocumentResult, makeUpperCased);
while (statement.getMoreResults()) {
try (ResultSet moreResults = statement.getResultSet()) {
xmlDocumentResult = addResultSetXmlPart(resultsElement, moreResults, xmlDocumentResult, makeUpperCased);
}
}
} 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) {
SoapUI.logError(e);
}
return out.toString();
}
public static Document addResultSetXmlPart(Element resultsElement, ResultSet rs, Document xmlDocumentResult, boolean uppercase)
throws SQLException {
final String TABLE_COLUMN_DELIMITER = ".";
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 i = 1; i <= colCount; i++) {
StringBuffer resultColumnName = new StringBuffer();
String tableName = rsmd.getTableName(i);
String columnName = rsmd.getColumnName(i);
if (uppercase) {
tableName = tableName.toUpperCase();
columnName = columnName.toUpperCase();
}
if (StringUtils.hasContent(tableName)) {
resultColumnName.append(tableName);
resultColumnName.append(TABLE_COLUMN_DELIMITER);
}
resultColumnName.append(columnName);
String xmlName = StringUtils.createXmlName(resultColumnName.toString());
Element node = xmlDocumentResult.createElement(xmlName);
String value = rs.getString(i);
if (StringUtils.hasContent(value)) {
Text textNode = xmlDocumentResult.createTextNode(value);
node.appendChild(textNode);
}
rowElement.appendChild(node);
}
resultSetElement.appendChild(rowElement);
}
return xmlDocumentResult;
}
}