View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2010 eviware.com 
3    *
4    *  soapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of version 2.1 of the GNU Lesser General Public License as published by 
6    *  the Free Software Foundation.
7    *
8    *  soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 
9    *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
10   *  See the GNU Lesser General Public License for more details at gnu.org.
11   */
12  
13  package com.eviware.soapui.support.xml;
14  
15  import java.io.IOException;
16  import java.io.InputStream;
17  import java.io.StringReader;
18  import java.io.StringWriter;
19  import java.io.Writer;
20  import java.sql.ResultSet;
21  import java.sql.ResultSetMetaData;
22  import java.sql.SQLException;
23  import java.sql.Statement;
24  import java.util.ArrayList;
25  import java.util.Collection;
26  import java.util.HashMap;
27  import java.util.HashSet;
28  import java.util.Iterator;
29  import java.util.List;
30  import java.util.Map;
31  import java.util.Set;
32  import java.util.StringTokenizer;
33  
34  import javax.xml.namespace.QName;
35  import javax.xml.parsers.DocumentBuilder;
36  import javax.xml.parsers.DocumentBuilderFactory;
37  import javax.xml.parsers.ParserConfigurationException;
38  
39  import net.sf.saxon.expr.Token;
40  import net.sf.saxon.expr.Tokenizer;
41  
42  import org.apache.log4j.Logger;
43  import org.apache.xmlbeans.SchemaType;
44  import org.apache.xmlbeans.XmlAnySimpleType;
45  import org.apache.xmlbeans.XmlCursor;
46  import org.apache.xmlbeans.XmlException;
47  import org.apache.xmlbeans.XmlObject;
48  import org.apache.xmlbeans.XmlOptions;
49  import org.apache.xmlbeans.XmlCursor.TokenType;
50  import org.w3c.dom.Attr;
51  import org.w3c.dom.CDATASection;
52  import org.w3c.dom.Document;
53  import org.w3c.dom.DocumentFragment;
54  import org.w3c.dom.Element;
55  import org.w3c.dom.NamedNodeMap;
56  import org.w3c.dom.Node;
57  import org.w3c.dom.NodeList;
58  import org.w3c.dom.ProcessingInstruction;
59  import org.w3c.dom.Text;
60  import org.xml.sax.InputSource;
61  import org.xml.sax.SAXException;
62  
63  import com.eviware.soapui.SoapUI;
64  import com.eviware.soapui.impl.wsdl.WsdlInterface;
65  import com.eviware.soapui.impl.wsdl.support.Constants;
66  import com.eviware.soapui.impl.wsdl.support.soap.SoapVersion;
67  import com.eviware.soapui.support.StringUtils;
68  import com.eviware.soapui.support.types.StringToStringMap;
69  
70  /***
71   * General XML-related utilities
72   */
73  
74  public final class XmlUtils
75  {
76  	private static DocumentBuilder documentBuilder;
77  	private final static Logger log = Logger.getLogger( XmlUtils.class );
78  
79  	static synchronized public Document parse( InputStream in )
80  	{
81  		try
82  		{
83  			return ensureDocumentBuilder().parse( in );
84  		}
85  		catch( Exception e )
86  		{
87  			log.error( "Error parsing InputStream; " + e.getMessage(), e );
88  		}
89  
90  		return null;
91  	}
92  
93  	static synchronized public Document parse( String fileName ) throws IOException
94  	{
95  		try
96  		{
97  			return ensureDocumentBuilder().parse( fileName );
98  		}
99  		catch( SAXException e )
100 		{
101 			log.error( "Error parsing fileName [" + fileName + "]; " + e.getMessage(), e );
102 		}
103 
104 		return null;
105 	}
106 
107 	public static String entitize( String xml )
108 	{
109 		return xml.replaceAll( "&", "&amp;" ).replaceAll( "<", "&lt;" ).replaceAll( ">", "&gt;" ).replaceAll( "\"",
110 				"&quot;" ).replaceAll( "'", "&apos;" );
111 	}
112 
113 	public static String entitizeContent( String xml )
114 	{
115 		return xml.replaceAll( "&", "&amp;" ).replaceAll( "\"", "&quot;" ).replaceAll( "'", "&apos;" );
116 	}
117 
118 	static synchronized public Document parse( InputSource inputSource ) throws IOException
119 	{
120 		try
121 		{
122 			return ensureDocumentBuilder().parse( inputSource );
123 		}
124 		catch( SAXException e )
125 		{
126 			throw new IOException( e.toString() );
127 		}
128 	}
129 
130 	private static DocumentBuilder ensureDocumentBuilder()
131 	{
132 		if( documentBuilder == null )
133 		{
134 			try
135 			{
136 				DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
137 				dbf.setNamespaceAware( true );
138 				documentBuilder = dbf.newDocumentBuilder();
139 			}
140 			catch( ParserConfigurationException e )
141 			{
142 				log.error( "Error creating DocumentBuilder; " + e.getMessage() );
143 			}
144 		}
145 
146 		return documentBuilder;
147 	}
148 
149 	public static String serializePretty( Document document )
150 	{
151 		try
152 		{
153 			Writer out = new StringWriter();
154 			serializePretty( document, out );
155 			return out.toString();
156 		}
157 		catch( IOException e )
158 		{
159 			log.error( "Failed to seraialize: " + e );
160 		}
161 		return null;
162 	}
163 
164 	public static void serializePretty( Document dom, Writer writer ) throws IOException
165 	{
166 		try
167 		{
168 			XmlObject xmlObject = XmlObject.Factory.parse( dom.getDocumentElement() );
169 			serializePretty( xmlObject, writer );
170 		}
171 		catch( Exception e )
172 		{
173 			throw new IOException( e.toString() );
174 		}
175 	}
176 
177 	public static void serializePretty( XmlObject xmlObject, Writer writer ) throws IOException
178 	{
179 		XmlOptions options = new XmlOptions();
180 		options.setSavePrettyPrint();
181 		options.setSavePrettyPrintIndent( 3 );
182 		options.setSaveNoXmlDecl();
183 		options.setSaveAggressiveNamespaces();
184 		// StringToStringMap map = new StringToStringMap();
185 		// map.put( SoapVersion.Soap11.getEnvelopeNamespace(), "SOAPENV" );
186 		// map.put( SoapVersion.Soap12.getEnvelopeNamespace(), "SOAPENV" );
187 		//
188 		// options.setSaveSuggestedPrefixes( map );
189 
190 		xmlObject.save( writer, options );
191 	}
192 
193 	public static void serialize( Document dom, Writer writer ) throws IOException
194 	{
195 		serialize( dom.getDocumentElement(), writer );
196 	}
197 
198 	public static void serialize( Element elm, Writer writer ) throws IOException
199 	{
200 		try
201 		{
202 			XmlObject xmlObject = XmlObject.Factory.parse( elm );
203 			xmlObject.save( writer );
204 		}
205 		catch( XmlException e )
206 		{
207 			throw new IOException( e.toString() );
208 		}
209 	}
210 
211 	static public String serialize( Node node, boolean prettyPrint )
212 	{
213 		try
214 		{
215 			XmlObject xmlObject = XmlObject.Factory.parse( node );
216 			return prettyPrint ? xmlObject.xmlText( new XmlOptions().setSavePrettyPrint() ) : xmlObject.xmlText();
217 		}
218 		catch( XmlException e )
219 		{
220 			return e.toString();
221 		}
222 	}
223 
224 	static public void setElementText( Element elm, String text )
225 	{
226 		Node node = elm.getFirstChild();
227 		if( node == null )
228 		{
229 			if( text != null )
230 				elm.appendChild( elm.getOwnerDocument().createTextNode( text ) );
231 		}
232 		else if( node.getNodeType() == Node.TEXT_NODE )
233 		{
234 			if( text == null )
235 				node.getParentNode().removeChild( node );
236 			else
237 				node.setNodeValue( text );
238 		}
239 		else if( text != null )
240 		{
241 			Text textNode = node.getOwnerDocument().createTextNode( text );
242 			elm.insertBefore( textNode, elm.getFirstChild() );
243 		}
244 	}
245 
246 	public static String getChildElementText( Element elm, String name )
247 	{
248 		Element child = getFirstChildElement( elm, name );
249 		return child == null ? null : getElementText( child );
250 	}
251 
252 	public static Element getFirstChildElement( Element elm )
253 	{
254 		return getFirstChildElement( elm, null );
255 	}
256 
257 	public static Element getFirstChildElement( Element elm, String name )
258 	{
259 		if( elm == null )
260 			return null;
261 
262 		NodeList nl = elm.getChildNodes();
263 		for( int c = 0; c < nl.getLength(); c++ )
264 		{
265 			Node node = nl.item( c );
266 			if( node.getNodeType() == Node.ELEMENT_NODE && ( name == null || node.getNodeName().equals( name ) ) )
267 				return ( Element )node;
268 		}
269 
270 		return null;
271 	}
272 
273 	public static Element getFirstChildElementNS( Element elm, String tns, String localName )
274 	{
275 		if( tns == null && localName == null )
276 			return getFirstChildElement( elm );
277 
278 		if( tns == null )
279 			return getFirstChildElement( elm, localName );
280 
281 		NodeList nl = elm.getChildNodes();
282 		for( int c = 0; c < nl.getLength(); c++ )
283 		{
284 			Node node = nl.item( c );
285 			if( node.getNodeType() != Node.ELEMENT_NODE )
286 				continue;
287 
288 			if( localName == null && tns.equals( node.getNamespaceURI() ) )
289 				return ( Element )node;
290 
291 			if( localName != null && tns.equals( node.getNamespaceURI() ) && localName.equals( node.getLocalName() ) )
292 				return ( Element )node;
293 		}
294 
295 		return null;
296 	}
297 
298 	static public String getElementText( Element elm )
299 	{
300 		Node node = elm.getFirstChild();
301 		if( node != null && node.getNodeType() == Node.TEXT_NODE )
302 			return node.getNodeValue();
303 
304 		return null;
305 	}
306 
307 	static public String getFragmentText( DocumentFragment elm )
308 	{
309 		Node node = elm.getFirstChild();
310 		if( node != null && node.getNodeType() == Node.TEXT_NODE )
311 			return node.getNodeValue();
312 
313 		return null;
314 	}
315 
316 	public static String getChildElementText( Element elm, String name, String defaultValue )
317 	{
318 		String result = getChildElementText( elm, name );
319 		return result == null ? defaultValue : result;
320 	}
321 
322 	static public String getNodeValue( Node node )
323 	{
324 		if( node.getNodeType() == Node.ELEMENT_NODE )
325 			return getElementText( ( Element )node );
326 		else if( node.getNodeType() == Node.DOCUMENT_FRAGMENT_NODE )
327 			return getFragmentText( ( DocumentFragment )node );
328 		else
329 			return node.getNodeValue();
330 	}
331 
332 	public static Node createNodeFromPath( Element modelElement, String path )
333 	{
334 		Document document = modelElement.getOwnerDocument();
335 		StringTokenizer st = new StringTokenizer( path, "/" );
336 		while( st.hasMoreTokens() )
337 		{
338 			String t = st.nextToken();
339 
340 			if( st.hasMoreTokens() )
341 			{
342 				if( t.equals( ".." ) )
343 				{
344 					modelElement = ( Element )modelElement.getParentNode();
345 				}
346 				else
347 				{
348 					Element elm = getFirstChildElement( modelElement, t );
349 					if( elm == null )
350 						modelElement = ( Element )modelElement.insertBefore( document.createElement( t ),
351 								getFirstChildElement( modelElement, t ) );
352 					else
353 						modelElement = elm;
354 				}
355 			}
356 			else
357 			{
358 				modelElement = ( Element )modelElement.insertBefore( document.createElement( t ), getFirstChildElement(
359 						modelElement, t ) );
360 			}
361 		}
362 
363 		return modelElement;
364 	}
365 
366 	public static Element addChildElement( Element element, String name, String text )
367 	{
368 		Document document = element.getOwnerDocument();
369 		Element result = ( Element )element.appendChild( document.createElement( name ) );
370 		if( text != null )
371 			result.appendChild( document.createTextNode( text ) );
372 
373 		return result;
374 	}
375 
376 	public static void setChildElementText( Element element, String name, String text )
377 	{
378 		Element elm = getFirstChildElement( element, name );
379 		if( elm == null )
380 		{
381 			elm = element.getOwnerDocument().createElement( name );
382 			element.appendChild( elm );
383 		}
384 
385 		setElementText( elm, text );
386 	}
387 
388 	public static Document parseXml( String xmlString ) throws IOException
389 	{
390 		return parse( new InputSource( new StringReader( xmlString ) ) );
391 	}
392 
393 	public static void dumpParserErrors( XmlObject xmlObject )
394 	{
395 		List<?> errors = new ArrayList<Object>();
396 		xmlObject.validate( new XmlOptions().setErrorListener( errors ) );
397 		for( Iterator<?> i = errors.iterator(); i.hasNext(); )
398 		{
399 			System.out.println( i.next() );
400 		}
401 	}
402 
403 	public static String transferValues( String source, String dest )
404 	{
405 		if( StringUtils.isNullOrEmpty( source ) || StringUtils.isNullOrEmpty( dest ) )
406 			return dest;
407 
408 		XmlCursor cursor = null;
409 		try
410 		{
411 			XmlObject sourceXml = XmlObject.Factory.parse( source );
412 			XmlObject destXml = XmlObject.Factory.parse( dest );
413 
414 			cursor = sourceXml.newCursor();
415 			cursor.toNextToken();
416 			while( !cursor.isEnddoc() )
417 			{
418 				while( !cursor.isContainer() && !cursor.isEnddoc() )
419 					cursor.toNextToken();
420 
421 				if( cursor.isContainer() )
422 				{
423 					Element elm = ( Element )cursor.getDomNode();
424 					String path = createXPath( elm );
425 					XmlObject[] paths = destXml.selectPath( path );
426 					if( paths != null && paths.length > 0 )
427 					{
428 						Element elm2 = ( Element )paths[0].getDomNode();
429 
430 						// transfer attributes
431 						transferAttributes( elm, elm2 );
432 
433 						// transfer text
434 						setElementText( elm2, getElementText( elm ) );
435 
436 						while( elm.getNextSibling() != null && elm2.getNextSibling() != null
437 								&& elm.getNextSibling().getNodeName().equals( elm.getNodeName() )
438 								&& !elm2.getNextSibling().getNodeName().equals( elm2.getNodeName() ) )
439 						{
440 							elm2 = ( Element )elm2.getParentNode().insertBefore(
441 									elm2.getOwnerDocument().createElementNS( elm2.getNamespaceURI(), elm2.getLocalName() ),
442 									elm2.getNextSibling() );
443 
444 							elm = ( Element )elm.getNextSibling();
445 
446 							// transfer attributes
447 							transferAttributes( elm, elm2 );
448 
449 							// transfer text
450 							setElementText( elm2, getElementText( elm ) );
451 						}
452 
453 					}
454 
455 					cursor.toNextToken();
456 				}
457 			}
458 
459 			return destXml.xmlText();
460 		}
461 		catch( Exception e )
462 		{
463 			SoapUI.logError( e );
464 		}
465 		finally
466 		{
467 			if( cursor != null )
468 				cursor.dispose();
469 		}
470 
471 		return dest;
472 	}
473 
474 	private static void transferAttributes( Element elm, Element elm2 )
475 	{
476 		NamedNodeMap attributes = elm.getAttributes();
477 		for( int c = 0; c < attributes.getLength(); c++ )
478 		{
479 			Attr attr = ( Attr )attributes.item( c );
480 			elm2.setAttributeNodeNS( ( Attr )elm2.getOwnerDocument().importNode( attr, true ) );
481 		}
482 	}
483 
484 	/***
485 	 * Returns absolute xpath for specified element, ignores namespaces
486 	 * 
487 	 * @param element
488 	 *           the element to create for
489 	 * @return the elements path in its containing document
490 	 */
491 
492 	public static String getElementPath( Element element )
493 	{
494 		Node elm = element;
495 
496 		String result = elm.getNodeName() + "[" + getElementIndex( elm ) + "]";
497 		while( elm.getParentNode() != null && elm.getParentNode().getNodeType() != Node.DOCUMENT_NODE )
498 		{
499 			elm = elm.getParentNode();
500 			result = elm.getNodeName() + "[" + getElementIndex( elm ) + "]/" + result;
501 		}
502 
503 		return "/" + result;
504 	}
505 
506 	/***
507 	 * Gets the index of the specified element amongst elements with the same
508 	 * name
509 	 * 
510 	 * @param element
511 	 *           the element to get for
512 	 * @return the index of the element, will be >= 1
513 	 */
514 
515 	public static int getElementIndex( Node element )
516 	{
517 		int result = 1;
518 
519 		Node elm = element.getPreviousSibling();
520 		while( elm != null )
521 		{
522 			if( elm.getNodeType() == Node.ELEMENT_NODE && elm.getNodeName().equals( element.getNodeName() ) )
523 				result++ ;
524 			elm = elm.getPreviousSibling();
525 		}
526 
527 		return result;
528 	}
529 
530 	public static String declareXPathNamespaces( String xmlString ) throws XmlException
531 	{
532 		return declareXPathNamespaces( XmlObject.Factory.parse( xmlString ) );
533 	}
534 
535 	public static synchronized String prettyPrintXml( String xml )
536 	{
537 		try
538 		{
539 			if( !XmlUtils.seemsToBeXml( xml ) )
540 				return xml;
541 
542 			StringWriter writer = new StringWriter();
543 			XmlUtils.serializePretty( XmlObject.Factory.parse( xml ), writer );
544 			return writer.toString();
545 		}
546 		catch( Exception e )
547 		{
548 			log.warn( "Failed to prettyPrint xml [" + xml + "]: " + e );
549 			return xml;
550 		}
551 	}
552 
553 	public static synchronized String prettyPrintXml( XmlObject xml )
554 	{
555 		try
556 		{
557 			if( xml == null )
558 				return null;
559 
560 			StringWriter writer = new StringWriter();
561 			XmlUtils.serializePretty( xml, writer );
562 			return writer.toString();
563 		}
564 		catch( Exception e )
565 		{
566 			log.warn( "Failed to prettyPrint xml [" + xml + "]: " + e );
567 			return xml.xmlText();
568 		}
569 	}
570 
571 	public static String declareXPathNamespaces( WsdlInterface iface )
572 	{
573 		StringBuffer buf = new StringBuffer();
574 		buf.append( "declare namespace soap='" );
575 		buf.append( iface.getSoapVersion().getEnvelopeNamespace() );
576 		buf.append( "';\n" );
577 
578 		try
579 		{
580 			Collection<String> namespaces = iface.getWsdlContext().getInterfaceDefinition().getDefinedNamespaces();
581 			int c = 1;
582 			for( Iterator<String> i = namespaces.iterator(); i.hasNext(); )
583 			{
584 				buf.append( "declare namespace ns" );
585 				buf.append( c++ );
586 				buf.append( "='" );
587 				buf.append( i.next() );
588 				buf.append( "';\n" );
589 			}
590 		}
591 		catch( Exception e )
592 		{
593 			SoapUI.logError( e );
594 		}
595 
596 		return buf.toString();
597 	}
598 
599 	public static String createXPath( Node node )
600 	{
601 		return createXPath( node, false, false, false, null );
602 	}
603 
604 	public static String createAbsoluteXPath( Node node )
605 	{
606 		return createXPath( node, false, false, true, null );
607 	}
608 
609 	public static String createXPath( Node node, boolean anonymous, boolean selectText, XPathModifier modifier )
610 	{
611 		return createXPath( node, anonymous, selectText, false, modifier );
612 	}
613 
614 	public static String createXPath( Node node, boolean anonymous, boolean selectText, boolean absolute,
615 			XPathModifier modifier )
616 	{
617 		XPathData xpathData = createXPathData( node, anonymous, selectText, absolute );
618 		if( xpathData == null )
619 			return null;
620 		return xpathData.buildXPath( modifier );
621 	}
622 
623 	public static XPathData createXPathData( Node node, boolean anonymous, boolean selectText, boolean absolute )
624 	{
625 		StringToStringMap nsMap = new StringToStringMap();
626 		List<String> pathComponents = new ArrayList<String>();
627 
628 		int nsCnt = 1;
629 
630 		String namespaceURI = node.getNamespaceURI();
631 		// if( node.getNodeType() == Node.TEXT_NODE )
632 		// {
633 		// node = node.getParentNode();
634 		// }
635 		if( node.getNodeType() == Node.ATTRIBUTE_NODE )
636 		{
637 			if( namespaceURI != null && namespaceURI.length() > 0 )
638 			{
639 				String prefix = node.getPrefix();
640 				if( prefix == null || prefix.length() == 0 )
641 					prefix = "ns" + nsCnt++ ;
642 
643 				nsMap.put( namespaceURI, prefix );
644 				pathComponents.add( "@" + prefix + ":" + node.getLocalName() );
645 			}
646 			else
647 			{
648 				pathComponents.add( "@" + node.getLocalName() );
649 			}
650 			node = ( ( Attr )node ).getOwnerElement();
651 		}
652 		else if( node.getNodeType() == Node.DOCUMENT_NODE )
653 		{
654 			node = ( ( Document )node ).getDocumentElement();
655 		}
656 		// else if( node.getNodeType() == Node.DOCUMENT_FRAGMENT_NODE )
657 		// {
658 		// node =
659 		// ((DocumentFragment)node).getOwnerDocument().getDocumentElement();
660 		// }
661 
662 		if( node.getNodeType() == Node.ELEMENT_NODE )
663 		{
664 			int index = anonymous ? 0 : findNodeIndex( node );
665 
666 			String pc = null;
667 
668 			namespaceURI = node.getNamespaceURI();
669 			if( namespaceURI != null && namespaceURI.length() > 0 )
670 			{
671 				String prefix = node.getPrefix();
672 				if( prefix == null || prefix.length() == 0 )
673 					prefix = "ns" + nsCnt++ ;
674 
675 				while( !nsMap.containsKey( namespaceURI ) && nsMap.containsValue( prefix ) )
676 				{
677 					prefix = "ns" + nsCnt++ ;
678 				}
679 
680 				nsMap.put( namespaceURI, prefix );
681 				pc = prefix + ":" + node.getLocalName();
682 			}
683 			else
684 			{
685 				pc = node.getLocalName();
686 			}
687 
688 			String elementText = XmlUtils.getElementText( ( Element )node );
689 
690 			// not an attribute?
691 			if( selectText && pathComponents.isEmpty() && elementText != null && elementText.trim().length() > 0 )
692 				pathComponents.add( "text()" );
693 
694 			pathComponents.add( pc + ( ( index == 0 ) ? "" : "[" + index + "]" ) );
695 		}
696 		else
697 			return null;
698 
699 		node = node.getParentNode();
700 		namespaceURI = node.getNamespaceURI();
701 		while( node != null
702 				&& node.getNodeType() == Node.ELEMENT_NODE
703 				&& ( absolute || ( !"Body".equals( node.getNodeName() )
704 						&& !SoapVersion.Soap11.getEnvelopeNamespace().equals( namespaceURI ) && !SoapVersion.Soap12
705 						.getEnvelopeNamespace().equals( namespaceURI ) ) ) )
706 		{
707 			int index = anonymous ? 0 : findNodeIndex( node );
708 
709 			String ns = nsMap.get( namespaceURI );
710 			String pc = null;
711 
712 			if( ns == null && namespaceURI != null && namespaceURI.length() > 0 )
713 			{
714 				String prefix = node.getPrefix();
715 				if( prefix == null || prefix.length() == 0 )
716 					prefix = "ns" + nsCnt++ ;
717 
718 				while( !nsMap.containsKey( namespaceURI ) && nsMap.containsValue( prefix ) )
719 				{
720 					prefix = "ns" + nsCnt++ ;
721 				}
722 
723 				nsMap.put( namespaceURI, prefix );
724 				ns = nsMap.get( namespaceURI );
725 
726 				pc = prefix + ":" + node.getLocalName();
727 			}
728 			else if( ns != null )
729 			{
730 				pc = ns + ":" + node.getLocalName();
731 			}
732 			else
733 			{
734 				pc = node.getLocalName();
735 			}
736 
737 			pathComponents.add( pc + ( ( index == 0 ) ? "" : "[" + index + "]" ) );
738 			node = node.getParentNode();
739 			namespaceURI = node.getNamespaceURI();
740 		}
741 
742 		return new XPathData( nsMap, pathComponents, absolute );
743 	}
744 
745 	private static int findNodeIndex( Node node )
746 	{
747 		String nm = node.getLocalName();
748 		String ns = node.getNamespaceURI();
749 		short nt = node.getNodeType();
750 
751 		Node parentNode = node.getParentNode();
752 		if( parentNode.getNodeType() != Node.ELEMENT_NODE )
753 			return 1;
754 
755 		Node child = parentNode.getFirstChild();
756 
757 		int ix = 0;
758 		while( child != null )
759 		{
760 			if( child == node )
761 				return ix + 1;
762 
763 			if( child.getNodeType() == nt
764 					&& nm.equals( child.getLocalName() )
765 					&& ( ( ns == null && child.getNamespaceURI() == null ) || ( ns != null && ns.equals( child
766 							.getNamespaceURI() ) ) ) )
767 				ix++ ;
768 
769 			child = child.getNextSibling();
770 		}
771 
772 		throw new RuntimeException( "Child node not found in parent!?" );
773 	}
774 
775 	public static boolean setNodeValue( Node domNode, String string )
776 	{
777 		if( domNode == null )
778 			return false;
779 
780 		short nodeType = domNode.getNodeType();
781 
782 		switch( nodeType )
783 		{
784 		case Node.ELEMENT_NODE :
785 		{
786 			setElementText( ( Element )domNode, string );
787 			break;
788 		}
789 		case Node.ATTRIBUTE_NODE :
790 		case Node.TEXT_NODE :
791 		{
792 			domNode.setNodeValue( string );
793 			break;
794 		}
795 		case Node.PROCESSING_INSTRUCTION_NODE :
796 		{
797 			( ( ProcessingInstruction )domNode ).setData( string );
798 			break;
799 		}
800 		case Node.CDATA_SECTION_NODE :
801 		{
802 			( ( CDATASection )domNode ).setData( string );
803 			break;
804 		}
805 		default :
806 		{
807 			return false;
808 		}
809 		}
810 
811 		return true;
812 	}
813 
814 	public static String declareXPathNamespaces( XmlObject xmlObject )
815 	{
816 		Map<QName, String> map = new HashMap<QName, String>();
817 		XmlCursor cursor = xmlObject.newCursor();
818 
819 		while( cursor.hasNextToken() )
820 		{
821 			if( cursor.toNextToken().isNamespace() )
822 				map.put( cursor.getName(), cursor.getTextValue() );
823 		}
824 
825 		cursor.dispose();
826 
827 		Iterator<QName> i = map.keySet().iterator();
828 		int nsCnt = 0;
829 
830 		StringBuffer buf = new StringBuffer();
831 		Set<String> prefixes = new HashSet<String>();
832 		Set<String> usedPrefixes = new HashSet<String>();
833 
834 		while( i.hasNext() )
835 		{
836 			QName name = i.next();
837 			String prefix = name.getLocalPart();
838 			if( prefix.length() == 0 )
839 				prefix = "ns" + Integer.toString( ++nsCnt );
840 			else if( prefix.equals( "xsd" ) || prefix.equals( "xsi" ) )
841 				continue;
842 
843 			if( usedPrefixes.contains( prefix ) )
844 			{
845 				int c = 1;
846 				while( usedPrefixes.contains( prefix + c ) )
847 					c++ ;
848 
849 				prefix = prefix + Integer.toString( c );
850 			}
851 			else
852 				prefixes.add( prefix );
853 
854 			buf.append( "declare namespace " );
855 			buf.append( prefix );
856 			buf.append( "='" );
857 			buf.append( map.get( name ) );
858 			buf.append( "';\n" );
859 
860 			usedPrefixes.add( prefix );
861 		}
862 
863 		return buf.toString();
864 	}
865 
866 	public static String setXPathContent( String xmlText, String xpath, String value )
867 	{
868 		try
869 		{
870 			XmlObject xmlObject = XmlObject.Factory.parse( xmlText );
871 
872 			String namespaces = declareXPathNamespaces( xmlObject );
873 			if( namespaces != null && namespaces.trim().length() > 0 )
874 				xpath = namespaces + xpath;
875 
876 			XmlObject[] path = xmlObject.selectPath( xpath );
877 			for( XmlObject xml : path )
878 			{
879 				setNodeValue( xml.getDomNode(), value );
880 			}
881 
882 			return xmlObject.toString();
883 		}
884 		catch( Exception e )
885 		{
886 			SoapUI.logError( e );
887 		}
888 
889 		return xmlText;
890 	}
891 
892 	public static QName getQName( Node node )
893 	{
894 		if( node == null )
895 			return null;
896 		else if( node.getNamespaceURI() == null )
897 			return new QName( node.getNodeName() );
898 		else
899 			return new QName( node.getNamespaceURI(), node.getLocalName() );
900 	}
901 
902 	public static String removeXPathNamespaceDeclarations( String xpath )
903 	{
904 		while( xpath.startsWith( "declare namespace" ) )
905 		{
906 			int ix = xpath.indexOf( ';' );
907 			if( ix == -1 )
908 				break;
909 
910 			xpath = xpath.substring( ix + 1 ).trim();
911 		}
912 		return xpath;
913 	}
914 
915 	public static String stripWhitespaces( String content )
916 	{
917 		try
918 		{
919 			XmlObject xml = XmlObject.Factory.parse( content, new XmlOptions().setLoadStripWhitespace()
920 					.setLoadStripComments() );
921 			content = xml.xmlText();
922 		}
923 		catch( Exception e )
924 		{
925 			SoapUI.logError( e );
926 		}
927 
928 		return content;
929 	}
930 
931 	public static NodeList getChildElements( Element elm )
932 	{
933 		List<Element> list = new ArrayList<Element>();
934 
935 		NodeList nl = elm.getChildNodes();
936 		for( int c = 0; c < nl.getLength(); c++ )
937 		{
938 			Node item = nl.item( c );
939 			if( item.getParentNode() == elm && item.getNodeType() == Node.ELEMENT_NODE )
940 				list.add( ( Element )item );
941 		}
942 
943 		return new ElementNodeList( list );
944 	}
945 
946 	public static NodeList getChildElementsByTagName( Element elm, String name )
947 	{
948 		List<Element> list = new ArrayList<Element>();
949 
950 		NodeList nl = elm.getChildNodes();
951 		for( int c = 0; c < nl.getLength(); c++ )
952 		{
953 			Node item = nl.item( c );
954 			if( item.getParentNode() == elm && item.getNodeType() == Node.ELEMENT_NODE && name.equals( item.getNodeName() ) )
955 				list.add( ( Element )item );
956 		}
957 
958 		return new ElementNodeList( list );
959 	}
960 
961 	public static NodeList getChildElementsOfType( Element elm, SchemaType schemaType )
962 	{
963 		List<Element> list = new ArrayList<Element>();
964 
965 		NodeList nl = elm.getChildNodes();
966 		for( int c = 0; c < nl.getLength(); c++ )
967 		{
968 			Node item = nl.item( c );
969 			if( item.getParentNode() == elm
970 					&& item.getNodeType() == Node.ELEMENT_NODE
971 					&& ( ( Element )item ).getAttributeNS( Constants.XSI_NS, "type" ).endsWith(
972 							":" + schemaType.getName().getLocalPart() ) )
973 			{
974 				list.add( ( Element )item );
975 			}
976 		}
977 
978 		return new ElementNodeList( list );
979 	}
980 
981 	public static NodeList getChildElementsNS( Element elm, QName name )
982 	{
983 		return getChildElementsByTagNameNS( elm, name.getNamespaceURI(), name.getLocalPart() );
984 	}
985 
986 	public static NodeList getChildElementsByTagNameNS( Element elm, String namespaceUri, String localName )
987 	{
988 		List<Element> list = new ArrayList<Element>();
989 
990 		NodeList nl = elm.getChildNodes();
991 		for( int c = 0; c < nl.getLength(); c++ )
992 		{
993 			Node item = nl.item( c );
994 			if( item.getParentNode() == elm && item.getNodeType() == Node.ELEMENT_NODE
995 					&& localName.equals( item.getLocalName() ) && namespaceUri.equals( item.getNamespaceURI() ) )
996 				list.add( ( Element )item );
997 		}
998 
999 		return new ElementNodeList( list );
1000 	}
1001 
1002 	public static String serialize( Document document )
1003 	{
1004 		StringWriter writer = new StringWriter();
1005 		try
1006 		{
1007 			serialize( document, writer );
1008 		}
1009 		catch( IOException e )
1010 		{
1011 			e.printStackTrace();
1012 		}
1013 		return writer.toString();
1014 	}
1015 
1016 	public static Element getFirstChildElementNS( Element domNode, QName name )
1017 	{
1018 		return getFirstChildElementNS( domNode, name.getNamespaceURI(), name.getLocalPart() );
1019 	}
1020 
1021 	public static QName findTypeNameForXsiType( String typeName, Element elm )
1022 	{
1023 		int ix = typeName.indexOf( ':' );
1024 		if( ix == -1 )
1025 			return null;
1026 
1027 		String prefix = typeName.substring( 0, ix );
1028 		String localName = typeName.substring( ix + 1 );
1029 		String namespaceUri = elm.getAttribute( "xmlns:" + prefix );
1030 
1031 		if( !StringUtils.hasContent( namespaceUri ) )
1032 			namespaceUri = findNamespaceForPrefix( elm, prefix );
1033 
1034 		if( StringUtils.hasContent( namespaceUri ) )
1035 		{
1036 			return new QName( namespaceUri, localName );
1037 		}
1038 
1039 		return null;
1040 	}
1041 
1042 	private static String findNamespaceForPrefix( Element elm, String prefix )
1043 	{
1044 		String namespaceUri = null;
1045 		while( StringUtils.isNullOrEmpty( namespaceUri ) && elm != null )
1046 		{
1047 			if( elm.getParentNode().getNodeType() != Node.ELEMENT_NODE )
1048 				break;
1049 
1050 			elm = ( Element )elm.getParentNode();
1051 			namespaceUri = elm.getAttribute( "xmlns:" + prefix );
1052 		}
1053 
1054 		return StringUtils.isNullOrEmpty( namespaceUri ) ? null : namespaceUri;
1055 	}
1056 
1057 	public static String findPrefixForNamespace( Element elm, String namespace )
1058 	{
1059 		while( elm != null )
1060 		{
1061 			NamedNodeMap attributes = elm.getAttributes();
1062 			for( int c = 0; c < attributes.getLength(); c++ )
1063 			{
1064 				if( attributes.item( c ).getNodeValue().equals( namespace )
1065 						&& attributes.item( c ).getNodeName().startsWith( "xmlns:" ) )
1066 				{
1067 					return attributes.item( c ).getNodeName().substring( 6 );
1068 				}
1069 			}
1070 
1071 			if( elm.getParentNode().getNodeType() != Node.ELEMENT_NODE )
1072 				break;
1073 
1074 			elm = ( Element )elm.getParentNode();
1075 		}
1076 
1077 		return null;
1078 	}
1079 
1080 	public static void setXsiType( Element elm, QName name )
1081 	{
1082 		String prefix = findPrefixForNamespace( elm, name.getNamespaceURI() );
1083 		if( prefix == null )
1084 		{
1085 			prefix = generatePrefixForNamespace( name.getNamespaceURI() );
1086 			while( findNamespaceForPrefix( elm, prefix ) != null )
1087 			{
1088 				prefix = generatePrefixForNamespace( name.getNamespaceURI() );
1089 			}
1090 
1091 			elm.setAttribute( "xmlns:" + prefix, name.getNamespaceURI() );
1092 		}
1093 
1094 		elm.setAttributeNS( Constants.XSI_NS, "type", prefix + ":" + name.getLocalPart() );
1095 	}
1096 
1097 	private static String generatePrefixForNamespace( String namespaceURI )
1098 	{
1099 		return "ns" + ( int )( Math.random() * 1000 );
1100 	}
1101 
1102 	public static QName createQName( Node node )
1103 	{
1104 		return new QName( node.getNamespaceURI(), node.getLocalName() );
1105 	}
1106 
1107 	public static Node getNextElementSibling( Node node )
1108 	{
1109 		node = node.getNextSibling();
1110 		while( node != null && node.getNodeType() != Node.ELEMENT_NODE )
1111 		{
1112 			node = node.getNextSibling();
1113 		}
1114 
1115 		return node;
1116 	}
1117 
1118 	public static Document createDocument( QName element )
1119 	{
1120 		ensureDocumentBuilder();
1121 
1122 		Document document = documentBuilder.newDocument();
1123 		document.appendChild( document.createElementNS( element.getNamespaceURI(), element.getLocalPart() ) );
1124 		return document;
1125 	}
1126 
1127 	public static String getValueForMatch( XmlCursor cursor )
1128 	{
1129 		Node domNode = cursor.getDomNode();
1130 		String stringValue;
1131 
1132 		if( domNode.getNodeType() == Node.ATTRIBUTE_NODE || domNode.getNodeType() == Node.TEXT_NODE )
1133 		{
1134 			stringValue = domNode.getNodeValue();
1135 		}
1136 		else if( cursor.getObject() instanceof XmlAnySimpleType )
1137 		{
1138 			stringValue = ( ( XmlAnySimpleType )cursor.getObject() ).getStringValue();
1139 		}
1140 		else
1141 		{
1142 			if( domNode.getNodeType() == Node.ELEMENT_NODE )
1143 			{
1144 				Element elm = ( Element )domNode;
1145 				if( elm.getChildNodes().getLength() == 1 && elm.getAttributes().getLength() == 0 )
1146 				{
1147 					stringValue = getElementText( elm );
1148 				}
1149 				else
1150 				{
1151 					stringValue = cursor.getObject().xmlText(
1152 							new XmlOptions().setSavePrettyPrint().setSaveOuter().setSaveAggressiveNamespaces() );
1153 				}
1154 			}
1155 			else
1156 			{
1157 				stringValue = domNode.getNodeValue();
1158 			}
1159 		}
1160 		return stringValue;
1161 	}
1162 
1163 	public static String getValueForMatch( Node domNode, boolean prettyPrintXml )
1164 	{
1165 		String stringValue;
1166 
1167 		if( domNode.getNodeType() == Node.ATTRIBUTE_NODE || domNode.getNodeType() == Node.TEXT_NODE )
1168 		{
1169 			stringValue = domNode.getNodeValue();
1170 		}
1171 		else
1172 		{
1173 			if( domNode.getNodeType() == Node.ELEMENT_NODE )
1174 			{
1175 				Element elm = ( Element )domNode;
1176 				if( elm.getChildNodes().getLength() == 1 && elm.getAttributes().getLength() == 0 )
1177 				{
1178 					stringValue = getElementText( elm );
1179 				}
1180 				else
1181 				{
1182 					stringValue = XmlUtils.serialize( domNode, prettyPrintXml );
1183 				}
1184 			}
1185 			else
1186 			{
1187 				stringValue = domNode.getNodeValue();
1188 			}
1189 		}
1190 
1191 		return stringValue;
1192 	}
1193 
1194 	public static String selectFirstNodeValue( XmlObject xmlObject, String xpath ) throws XmlException
1195 	{
1196 		Node domNode = selectFirstDomNode( xmlObject, xpath );
1197 		return domNode == null ? null : getNodeValue( domNode );
1198 	}
1199 
1200 	public static String[] selectNodeValues( XmlObject xmlObject, String xpath )
1201 	{
1202 		Node[] nodes = selectDomNodes( xmlObject, xpath );
1203 
1204 		String[] result = new String[nodes.length];
1205 		for( int c = 0; c < nodes.length; c++ )
1206 		{
1207 			result[c] = getNodeValue( nodes[c] );
1208 		}
1209 
1210 		return result;
1211 	}
1212 
1213 	public static Node selectFirstDomNode( XmlObject xmlObject, String xpath )
1214 	{
1215 		XmlCursor cursor = xmlObject.newCursor();
1216 		try
1217 		{
1218 			cursor.selectPath( xpath );
1219 
1220 			if( cursor.toNextSelection() )
1221 			{
1222 				return cursor.getDomNode();
1223 			}
1224 			else
1225 				return null;
1226 		}
1227 		finally
1228 		{
1229 			cursor.dispose();
1230 		}
1231 	}
1232 
1233 	public static Node[] selectDomNodes( XmlObject xmlObject, String xpath )
1234 	{
1235 		List<Node> result = new ArrayList<Node>();
1236 
1237 		XmlCursor cursor = xmlObject.newCursor();
1238 		try
1239 		{
1240 			cursor.selectPath( xpath );
1241 
1242 			while( cursor.toNextSelection() )
1243 			{
1244 				result.add( cursor.getDomNode() );
1245 			}
1246 		}
1247 		finally
1248 		{
1249 			cursor.dispose();
1250 		}
1251 
1252 		return result.toArray( new Node[result.size()] );
1253 	}
1254 
1255 	private final static class ElementNodeList implements NodeList
1256 	{
1257 		private final List<Element> list;
1258 
1259 		public ElementNodeList( List<Element> list )
1260 		{
1261 			this.list = list;
1262 		}
1263 
1264 		public int getLength()
1265 		{
1266 			return list.size();
1267 		}
1268 
1269 		public Node item( int index )
1270 		{
1271 			return list.get( index );
1272 		}
1273 	}
1274 
1275 	public static boolean seemsToBeXml( String str )
1276 	{
1277 		try
1278 		{
1279 			if( StringUtils.isNullOrEmpty( str ) )
1280 				return false;
1281 
1282 			return null != XmlObject.Factory.parse( str );
1283 		}
1284 		catch( Throwable e )
1285 		{
1286 			return false;
1287 		}
1288 	}
1289 
1290 	public static String extractNamespaces( String xpath )
1291 	{
1292 		String result = xpath;
1293 		int ix = xpath.lastIndexOf( "declare namespace" );
1294 		if( ix != -1 )
1295 		{
1296 			ix = xpath.indexOf( '\'', ix + 1 );
1297 			if( ix != -1 )
1298 			{
1299 				ix = xpath.indexOf( '\'', ix + 1 );
1300 				if( ix != -1 )
1301 				{
1302 					ix = xpath.indexOf( ';' );
1303 					if( ix != -1 )
1304 					{
1305 						result = xpath.substring( 0, ix + 1 );
1306 					}
1307 				}
1308 			}
1309 		}
1310 		else
1311 		{
1312 			result = "";
1313 		}
1314 
1315 		return result;
1316 	}
1317 
1318 	public static String removeUnneccessaryNamespaces( String xml )
1319 	{
1320 		if( StringUtils.isNullOrEmpty( xml ) )
1321 			return xml;
1322 
1323 		XmlObject xmlObject = null;
1324 		XmlCursor cursor = null;
1325 		try
1326 		{
1327 			xmlObject = XmlObject.Factory.parse( xml );
1328 
1329 			cursor = xmlObject.newCursor();
1330 			while( cursor.currentTokenType() != TokenType.START && cursor.currentTokenType() != TokenType.ENDDOC )
1331 			{
1332 				cursor.toNextToken();
1333 			}
1334 
1335 			if( cursor.currentTokenType() == TokenType.START )
1336 			{
1337 				Map<?, ?> nsMap = new HashMap<Object, Object>();
1338 
1339 				cursor.getAllNamespaces( nsMap );
1340 				nsMap.remove( cursor.getDomNode().getPrefix() );
1341 
1342 				NamedNodeMap attributes = cursor.getDomNode().getAttributes();
1343 				for( int c = 0; attributes != null && c < attributes.getLength(); c++ )
1344 				{
1345 					nsMap.remove( attributes.item( c ).getPrefix() );
1346 				}
1347 
1348 				if( cursor.toFirstChild() )
1349 				{
1350 					while( cursor.getDomNode() != xmlObject.getDomNode() )
1351 					{
1352 						attributes = cursor.getDomNode().getAttributes();
1353 						for( int c = 0; attributes != null && c < attributes.getLength(); c++ )
1354 						{
1355 							nsMap.remove( attributes.item( c ).getPrefix() );
1356 						}
1357 
1358 						nsMap.remove( cursor.getDomNode().getPrefix() );
1359 						cursor.toNextToken();
1360 					}
1361 				}
1362 
1363 				xml = xmlObject.xmlText( new XmlOptions().setSaveOuter().setSavePrettyPrint().setSaveImplicitNamespaces(
1364 						nsMap ) );
1365 			}
1366 		}
1367 		catch( XmlException e )
1368 		{
1369 
1370 		}
1371 		finally
1372 		{
1373 			if( cursor != null )
1374 				cursor.dispose();
1375 		}
1376 
1377 		return xml;
1378 	}
1379 
1380 	public static String replaceNameInPathOrQuery( String pathOrQuery, String oldName, String newName ) throws Exception
1381 	{
1382 		Tokenizer t = new Tokenizer();
1383 		t.tokenize( pathOrQuery, 0, -1, 1 );
1384 		StringBuffer result = new StringBuffer();
1385 		int lastIx = 0;
1386 
1387 		while( t.currentToken != Token.EOF )
1388 		{
1389 			if( t.currentToken == Token.NAME && t.currentTokenValue.equals( oldName ) )
1390 			{
1391 				result.append( pathOrQuery.substring( lastIx, t.currentTokenStartOffset ) );
1392 				result.append( newName );
1393 				lastIx = t.currentTokenStartOffset + t.currentTokenValue.length();
1394 			}
1395 
1396 			t.next();
1397 		}
1398 
1399 		if( lastIx < pathOrQuery.length() )
1400 			result.append( pathOrQuery.substring( lastIx ) );
1401 		//
1402 		System.out.println( "returning " + result.toString() );
1403 		return result.toString();
1404 	}
1405 
1406 	public static QName getQName( XmlObject contentElement )
1407 	{
1408 		return contentElement == null ? null : getQName( contentElement.getDomNode() );
1409 	}
1410 
1411 	public static String getXPathValue( String value, String xpath )
1412 	{
1413 		try
1414 		{
1415 			XmlObject xmlObject = XmlObject.Factory.parse( value );
1416 			XmlObject[] nodes = xmlObject.selectPath( xpath );
1417 			if( nodes.length > 0 )
1418 				return getNodeValue( nodes[0].getDomNode() );
1419 		}
1420 		catch( XmlException e )
1421 		{
1422 			e.printStackTrace();
1423 		}
1424 
1425 		return null;
1426 	}
1427 
1428 	public static Document createJdbcXmlResult( Statement statement ) throws SQLException, ParserConfigurationException
1429 	{
1430 		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
1431 		DocumentBuilder builder = factory.newDocumentBuilder();
1432 		org.w3c.dom.Document xmlDocumentResult = builder.newDocument();
1433 		Element resultsElement = xmlDocumentResult.createElement( "Results" );
1434 		xmlDocumentResult.appendChild( resultsElement );
1435 
1436 		ResultSet resultSet = statement.getResultSet();
1437 		if( resultSet != null )
1438 		{
1439 			resultSet.setFetchSize( statement.getFetchSize() );
1440 			xmlDocumentResult = addResultSetXmlPart( resultsElement, resultSet, xmlDocumentResult );
1441 			while( statement.getMoreResults() )
1442 			{
1443 				xmlDocumentResult = addResultSetXmlPart( resultsElement, statement.getResultSet(), xmlDocumentResult );
1444 			}
1445 		}
1446 		else
1447 		{
1448 			Element errorElement = xmlDocumentResult.createElement( "UpdateCount" );
1449 			errorElement.appendChild( xmlDocumentResult.createTextNode( String.valueOf( statement.getUpdateCount() ) ) );
1450 			resultsElement.appendChild( errorElement );
1451 		}
1452 
1453 		return xmlDocumentResult;
1454 	}
1455 
1456 	public static Document addResultSetXmlPart( Element resultsElement, ResultSet rs, Document xmlDocumentResult )
1457 			throws SQLException
1458 	{
1459 		// resultSet = statement.getResultSet();
1460 		// connection to an ACCESS MDB
1461 		ResultSetMetaData rsmd = rs.getMetaData();
1462 		Element resultSetElement = xmlDocumentResult.createElement( "ResultSet" );
1463 
1464 		resultSetElement.setAttribute( "fetchSize", String.valueOf( rs.getFetchSize() ) );
1465 		resultsElement.appendChild( resultSetElement );
1466 
1467 		int colCount = rsmd.getColumnCount();
1468 		while( rs.next() )
1469 		{
1470 			Element rowElement = xmlDocumentResult.createElement( "Row" );
1471 			rowElement.setAttribute( "rowNumber", String.valueOf( rs.getRow() ) );
1472 
1473 			resultsElement.appendChild( rowElement );
1474 			for( int ii = 1; ii <= colCount; ii++ )
1475 			{
1476 				String columnName = "";
1477 				if( !StringUtils.isNullOrEmpty( rsmd.getTableName( ii ) ) )
1478 				{
1479 					columnName += ( rsmd.getTableName( ii ) ).toUpperCase() + ".";
1480 				}
1481 				columnName += ( rsmd.getColumnName( ii ) ).toUpperCase();
1482 				String value = rs.getString( ii );
1483 				Element node = xmlDocumentResult.createElement( columnName );
1484 				if( !StringUtils.isNullOrEmpty( value ) )
1485 				{
1486 					node.appendChild( xmlDocumentResult.createTextNode( value.toString() ) );
1487 				}
1488 				rowElement.appendChild( node );
1489 			}
1490 			resultSetElement.appendChild( rowElement );
1491 		}
1492 		return xmlDocumentResult;
1493 	}
1494 
1495 }