View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2007 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.OutputStreamWriter;
18  import java.io.StringReader;
19  import java.io.StringWriter;
20  import java.io.Writer;
21  import java.util.ArrayList;
22  import java.util.Collection;
23  import java.util.HashMap;
24  import java.util.HashSet;
25  import java.util.Iterator;
26  import java.util.List;
27  import java.util.Map;
28  import java.util.Set;
29  import java.util.StringTokenizer;
30  
31  import javax.xml.namespace.QName;
32  import javax.xml.parsers.DocumentBuilder;
33  import javax.xml.parsers.DocumentBuilderFactory;
34  import javax.xml.parsers.ParserConfigurationException;
35  
36  import org.apache.log4j.Logger;
37  import org.apache.xmlbeans.XmlCursor;
38  import org.apache.xmlbeans.XmlException;
39  import org.apache.xmlbeans.XmlObject;
40  import org.apache.xmlbeans.XmlOptions;
41  import org.w3c.dom.Attr;
42  import org.w3c.dom.Document;
43  import org.w3c.dom.DocumentFragment;
44  import org.w3c.dom.Element;
45  import org.w3c.dom.NamedNodeMap;
46  import org.w3c.dom.Node;
47  import org.w3c.dom.NodeList;
48  import org.w3c.dom.Text;
49  import org.xml.sax.InputSource;
50  import org.xml.sax.SAXException;
51  
52  import com.eviware.soapui.SoapUI;
53  import com.eviware.soapui.impl.wsdl.WsdlInterface;
54  import com.eviware.soapui.impl.wsdl.support.soap.SoapVersion;
55  import com.eviware.soapui.support.types.StringToStringMap;
56  
57  /***
58   * General XML-related utilities
59   */
60  
61  public final class XmlUtils
62  {
63     private static DocumentBuilder documentBuilder;
64     private final static Logger log = Logger.getLogger( XmlUtils.class );
65  
66     static public Document parse( InputStream in )
67     {
68        try
69        {
70           return ensureDocumentBuilder().parse( in );
71        }
72        catch( Exception e )
73        {
74        	log.error( "Error parsing InputStream; " + e.getMessage(), e );
75        }
76  
77        return null;
78     }
79  
80     static public Document parse( String fileName ) throws IOException
81     {
82        try
83        {
84           return  ensureDocumentBuilder().parse( fileName );
85        }
86        catch( SAXException e )
87        {
88        	log.error( "Error parsing fileName [" + fileName + "]; " + e.getMessage(), e );
89        }
90  
91        return null;
92     }
93     
94     public static String entitize( String xml )
95     {
96     	return xml.replaceAll( "&", "&amp;" ).replaceAll( "<", "&lt;" ).replaceAll( ">", "&gt;" ).
97     		replaceAll( "\"", "&quot;" ).replaceAll( "'", "&apos;" );
98     }
99  
100    static public Document parse( InputSource inputSource ) throws IOException
101    {
102       try
103       {
104          return ensureDocumentBuilder().parse( inputSource );
105       }
106       catch( SAXException e )
107       {
108       	throw new IOException( e.toString() );
109       }
110    }
111 
112    private static DocumentBuilder ensureDocumentBuilder()
113    {
114       if( documentBuilder == null )
115       {
116          try
117          {
118             DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
119             dbf.setNamespaceAware( true );
120 				documentBuilder = dbf.newDocumentBuilder();
121          }
122          catch( ParserConfigurationException e )
123          {
124          	log.error( "Error creating DocumentBuilder; " + e.getMessage() );
125          }
126       }
127 
128       return documentBuilder;
129    }
130 
131    public static void serializePretty( Document document )
132    {
133       try
134       {
135          serializePretty( document, new OutputStreamWriter( System.out ) );
136       }
137       catch( IOException e )
138       {
139          log.error( "Failed to seraialize: " + e );
140       }
141    }
142 
143    public static void serializePretty( Document dom, Writer writer )
144       throws IOException
145    {
146    	try
147 		{
148 			XmlObject xmlObject = XmlObject.Factory.parse(dom.getDocumentElement());
149 			serializePretty(xmlObject, writer);
150 		}
151 		catch (Exception e)
152 		{
153 			throw new IOException( e.toString() );
154 		}
155    }
156    
157    public static void serializePretty( XmlObject xmlObject, Writer writer ) throws IOException
158 	{
159 		XmlOptions options = new XmlOptions();
160 		options.setSavePrettyPrint();
161 		options.setSavePrettyPrintIndent( 3 );
162 		options.setSaveNoXmlDecl();
163 		options.setSaveAggressiveNamespaces();
164 		xmlObject.save(writer, options);
165 	}
166 
167    public static void serialize( Document dom, Writer writer )
168    throws IOException
169 	{
170    	serialize( dom.getDocumentElement(), writer );
171 	}
172    
173    public static void serialize( Element elm, Writer writer )
174    throws IOException
175 	{
176    	try
177 		{
178 			XmlObject xmlObject = XmlObject.Factory.parse(elm);
179 			xmlObject.save( writer );
180 		}
181 		catch (XmlException e)
182 		{
183 			throw new IOException( e.toString() );
184 		}
185 	}
186    
187    static public void setElementText( Element elm, String text )
188    {
189       Node node = elm.getFirstChild();
190       if( node == null  )
191       {
192       	if( text != null)
193       		elm.appendChild( elm.getOwnerDocument().createTextNode( text ) );
194       }
195       else if( node.getNodeType() == Node.TEXT_NODE )
196       {
197          if( text == null )
198             node.getParentNode().removeChild( node );
199          else
200             node.setNodeValue( text );
201       }
202       else if( text != null )
203       {
204          Text textNode = node.getOwnerDocument().createTextNode( text );
205          elm.insertBefore( textNode, elm.getFirstChild() );
206       }
207    }
208 
209    public static String getChildElementText( Element elm, String name )
210    {
211       Element child = getFirstChildElement( elm, name );
212       return child == null ? null : getElementText( child );
213    }
214 
215    public static Element getFirstChildElement( Element elm )
216    {
217    	return getFirstChildElement( elm, null );
218    }
219    
220    public static Element getFirstChildElement( Element elm, String name )
221    {
222       NodeList nl = elm.getChildNodes();
223       for( int c = 0; c < nl.getLength(); c++ )
224       {
225          Node node = nl.item( c );
226          if( node.getNodeType() == Node.ELEMENT_NODE && (name == null || node.getNodeName().equals( name )) )
227             return (Element) node;
228       }
229 
230       return null;
231    }
232    
233    public static Element getFirstChildElementNS( Element elm, String tns, String localName )
234    {
235    	if( tns == null && localName == null )
236    		return getFirstChildElement( elm );
237    	
238    	if( tns == null )
239    		return getFirstChildElement( elm, localName );
240    	
241       NodeList nl = elm.getChildNodes();
242       for( int c = 0; c < nl.getLength(); c++ )
243       {
244          Node node = nl.item( c );
245          if( node.getNodeType() != Node.ELEMENT_NODE ) continue;
246          
247          if( localName == null && tns.equals( node.getNamespaceURI() ))
248          	return ( Element ) node;
249          
250          if( localName != null && tns.equals( node.getNamespaceURI() ) && localName.equals( node.getLocalName() ))
251          	return ( Element ) node;
252       }
253 
254       return null;
255    }
256 
257    static public String getElementText( Element elm )
258    {
259       Node node = elm.getFirstChild();
260       if( node != null && node.getNodeType() == Node.TEXT_NODE )
261          return node.getNodeValue();
262 
263       return null;
264    }
265    
266    static public String getFragmentText( DocumentFragment elm )
267    {
268       Node node = elm.getFirstChild();
269       if( node != null && node.getNodeType() == Node.TEXT_NODE )
270          return node.getNodeValue();
271 
272       return null;
273    }
274 
275    public static String getChildElementText( Element elm, String name, String defaultValue )
276    {
277       String result = getChildElementText( elm, name );
278       return result == null ? defaultValue : result;
279    }
280 
281    static public String getNodeValue( Node node )
282    {
283    	if( node.getNodeType() == Node.ELEMENT_NODE )
284    		return getElementText( (Element) node );
285    	else if( node.getNodeType() == Node.DOCUMENT_FRAGMENT_NODE )
286    		return getFragmentText( (DocumentFragment) node );
287    	else 
288    		return node.getNodeValue();
289    }
290 
291    public static Node createNodeFromPath( Element modelElement, String path )
292    {
293       Document document = modelElement.getOwnerDocument();
294       StringTokenizer st = new StringTokenizer( path, "/" );
295       while( st.hasMoreTokens() )
296       {
297          String t = st.nextToken();
298 
299          if( st.hasMoreTokens() )
300          {
301             if( t.equals( ".." ) )
302             {
303                modelElement = (Element) modelElement.getParentNode();
304             }
305             else
306             {
307                Element elm = getFirstChildElement( modelElement, t );
308                if( elm == null )
309                   modelElement = (Element) modelElement.insertBefore(
310                      document.createElement( t ),
311                      getFirstChildElement( modelElement, t ) );
312                else
313                   modelElement = elm;
314             }
315          }
316          else
317          {
318             modelElement = (Element) modelElement.insertBefore(
319                document.createElement( t ),
320                getFirstChildElement( modelElement, t ) );
321          }
322       }
323 
324       return modelElement;
325    }
326 
327    public static Element addChildElement( Element element, String name, String text )
328    {
329       Document document = element.getOwnerDocument();
330       Element result = (Element) element.appendChild( document.createElement( name ) );
331       if( text != null )
332          result.appendChild( document.createTextNode( text ) );
333 
334       return result;
335    }
336 
337    public static void setChildElementText( Element element, String name, String text )
338    {
339       Element elm = getFirstChildElement( element, name );
340       if( elm == null )
341       {
342          elm = element.getOwnerDocument().createElement( name );
343          element.appendChild( elm );
344       }
345 
346       setElementText( elm, text );
347    }
348 
349    public static Document parseXml( String xmlString ) throws IOException
350    {
351       return parse( new InputSource( new StringReader( xmlString )));
352    }
353    
354    public static void dumpParserErrors(XmlObject xmlObject)
355    {
356       List errors = new ArrayList();
357       xmlObject.validate(new XmlOptions().setErrorListener(errors));
358       for (Iterator i = errors.iterator(); i.hasNext();)
359       {
360          System.out.println(i.next());
361       }
362    }
363 
364 	public static String transferValues(String source, String dest)
365 	{
366 		XmlCursor cursor = null;
367 		try
368 		{
369 			XmlObject sourceXml = XmlObject.Factory.parse( source );
370 			XmlObject destXml = XmlObject.Factory.parse( dest );
371 			
372 			cursor = sourceXml.newCursor();
373 			cursor.toNextToken();
374 			while( !cursor.isEnddoc() )
375 			{
376 				while( !cursor.isContainer() && !cursor.isEnddoc() )
377 					cursor.toNextToken();
378 				
379 				if( cursor.isContainer() )
380 				{
381 					Element elm = ( Element ) cursor.getDomNode();
382 					String path = createXPath( elm );
383 					XmlObject[] paths = destXml.selectPath( path );
384 					if( paths != null && paths.length > 0 )
385 					{
386 						Element elm2 = ( Element ) paths[0].getDomNode();
387 						
388 						// transfer attributes
389 						NamedNodeMap attributes = elm.getAttributes();
390 						for( int c = 0; c < attributes.getLength(); c++ )
391 						{
392 							Attr attr = (Attr) attributes.item( c );
393 							elm2.setAttribute( attr.getNodeName(), attr.getNodeValue() );
394 						}
395 						
396 						// transfer text
397 						setElementText( elm2, getElementText( elm ));
398 					}
399 					
400 					cursor.toNextToken();
401 				}
402 			}
403 
404 			return destXml.xmlText();
405 		}
406 		catch (Exception e)
407 		{
408 			SoapUI.logError( e );
409 		}
410 		finally
411 		{
412 			if( cursor != null )
413 				cursor.dispose();
414 		}
415 		
416 		return dest;
417 	}
418 
419 	/***
420 	 * Returns absolute xpath for specified element, ignores namespaces
421 	 *  
422 	 * @param elm the element to create for
423 	 * @return the elements path in its containing document
424 	 */
425 	
426 	public static String getElementPath(Element element)
427 	{
428 		Node elm = element;
429 		
430 		String result = elm.getNodeName() + "[" + getElementIndex( elm ) + "]";
431 		while( elm.getParentNode() != null && elm.getParentNode().getNodeType() != Node.DOCUMENT_NODE )
432 		{
433 			elm = elm.getParentNode();
434 			result = elm.getNodeName() + "[" + getElementIndex( elm ) + "]/" + result;
435 		}
436 
437 		return "/" + result;
438 	}
439 
440 	/***
441 	 * Gets the index of the specified element amongst elements with the same name
442 	 * 
443 	 * @param element the element to get for
444 	 * @return the index of the element, will be >= 1
445 	 */
446 	
447 	public static int getElementIndex(Node element)
448 	{
449 		int result = 1;
450 		
451 		Node elm = element.getPreviousSibling();
452 		while( elm != null )
453 		{
454 			if( elm.getNodeType() == Node.ELEMENT_NODE && elm.getNodeName().equals( element.getNodeName() ))
455 				result++;
456 			elm = elm.getPreviousSibling();
457 		}
458 		
459 		return result;	
460 	}
461 	
462 	public static String declareXPathNamespaces( String xmlString ) throws XmlException
463 	{
464 		return declareXPathNamespaces( XmlObject.Factory.parse(xmlString));
465 	}
466 	
467 	public static synchronized String prettyPrintXml( String xml )
468 	{
469       try
470       {
471       	if( xml == null )
472       		return null;
473       	
474          StringWriter writer = new StringWriter();
475          XmlUtils.serializePretty( XmlObject.Factory.parse( xml ), writer );
476          return writer.toString();
477       }
478       catch( Exception e )
479       {
480       	log.warn( "Failed to prettyPrint xml: " + e );
481          return xml;
482       }
483 	}
484 	
485 	public static synchronized String prettyPrintXml( XmlObject xml )
486 	{
487       try
488       {
489       	if( xml == null )
490       		return null;
491       	
492          StringWriter writer = new StringWriter();
493          XmlUtils.serializePretty( xml, writer );
494          return writer.toString();
495       }
496       catch( Exception e )
497       {
498       	log.warn( "Failed to prettyPrint xml: " + e );
499          return xml.xmlText();
500       }
501 	}
502 
503 	public static String declareXPathNamespaces(WsdlInterface iface)
504 	{
505 		StringBuffer buf = new StringBuffer();
506 		buf.append( "declare namespace soap='" );
507 		buf.append( iface.getSoapVersion().getEnvelopeNamespace() );
508 		buf.append( "';\n");
509 		
510 		try
511 		{
512 			Collection<String> namespaces = iface.getWsdlContext().getDefinedNamespaces();
513 			int c = 1;
514 			for (Iterator<String> i = namespaces.iterator(); i.hasNext();)
515 			{
516 				buf.append("declare namespace ns");
517 				buf.append(c++);
518 				buf.append("='");
519 				buf.append(i.next());
520 				buf.append("';\n");
521 			}
522 		}
523 		catch (Exception e)
524 		{
525 			SoapUI.logError( e );
526 		}		
527 		
528 		return buf.toString();
529 	}
530 	
531 	public static String createXPath(Node node )
532 	{
533 		return createXPath( node, false, false, null );
534 	}
535 	
536 	public static String createXPath(Node node, boolean anonymous, boolean selectText, XPathModifier modifier )
537 	{
538 		StringToStringMap nsMap = new StringToStringMap();
539 		int nsCnt = 1;
540 		List<String> pathComponents = new ArrayList<String>();
541 		
542 		String namespaceURI = node.getNamespaceURI();
543 		if( node.getNodeType() == Node.ATTRIBUTE_NODE )
544 		{
545 			if( namespaceURI.length() > 0 )
546 			{
547 				String prefix = node.getPrefix();
548 				if( prefix == null || prefix.length() == 0 )
549 					prefix = "ns" + nsCnt++;
550 				
551 				nsMap.put( namespaceURI, prefix );
552 				pathComponents.add( "@" + prefix + ":" + node.getLocalName() );
553 			}
554 			else
555 			{
556 				pathComponents.add( "@" + node.getLocalName() );
557 			}
558 			node = ((Attr)node).getOwnerElement();
559 		}
560 		
561 		if( node.getNodeType() == Node.ELEMENT_NODE )
562 		{
563 			int index = anonymous ? 0 : findNodeIndex( node );
564 			
565 			String pc = null;
566 		
567 			namespaceURI = node.getNamespaceURI();
568 			if( namespaceURI.length() > 0 )
569 			{
570 				String prefix = node.getPrefix();
571 				if( prefix == null || prefix.length() == 0 )
572 					prefix = "ns" + nsCnt++;
573 				
574 				nsMap.put( namespaceURI, prefix );
575 				pc = prefix + ":" + node.getLocalName();
576 			}
577 			else
578 			{
579 				pc = node.getLocalName();
580 			}
581 			
582 			String elementText = XmlUtils.getElementText( (Element) node );
583 			
584 			// not an attribute?
585 			if( selectText && pathComponents.isEmpty() && elementText != null && elementText.trim().length() > 0  )
586 				pathComponents.add( "text()" );
587 			
588 			pathComponents.add( pc + ((index == 0 ) ? "" : "[" + index + "]" ));
589 		}
590 		else
591 			return null;
592 		
593 		node = node.getParentNode();
594 		namespaceURI = node.getNamespaceURI();
595 		while( node != null && node.getNodeType() == Node.ELEMENT_NODE && 
596 				!node.getNodeName().equals( "Body" ) && 
597 				!namespaceURI.equals( SoapVersion.Soap11.getEnvelopeNamespace() ) &&
598 				!namespaceURI.equals( SoapVersion.Soap12.getEnvelopeNamespace() ))
599 		{
600 			int index = anonymous ? 0 : findNodeIndex( node );
601 			
602 			String ns = nsMap.get( namespaceURI );
603 			String pc = null;
604 			
605 			if( ns == null && namespaceURI.length() > 0 )
606 			{
607 				String prefix = node.getPrefix();
608 				if( prefix == null || prefix.length() == 0 )
609 					prefix = "ns" + nsCnt++;
610 				
611 				nsMap.put( namespaceURI, prefix );
612 				ns = nsMap.get( namespaceURI );
613 				
614 				pc = prefix + ":" + node.getLocalName();
615 			}
616 			else if( ns != null ) 
617 			{
618 				 pc = ns + ":" + node.getLocalName();
619 			}
620 			else
621 			{
622 				 pc = node.getLocalName();
623 			}
624 			
625 			pathComponents.add( pc + ((index == 0 ) ? "" : "[" + index + "]" ));
626 			node = node.getParentNode();
627 			namespaceURI = node.getNamespaceURI();
628 		}
629 		
630 		StringBuffer xpath = new StringBuffer();
631 
632 		for( Iterator<String> i = nsMap.keySet().iterator(); i.hasNext(); )
633 		{
634 			String ns = i.next();
635 			xpath.append( "declare namespace " + nsMap.get( ns ) + "='" + ns + "';\n");
636 		}
637 		
638 		if( modifier != null )
639 			modifier.beforeSelector( xpath );
640 		
641 		xpath.append( "/" );
642 		
643 		for( int c = pathComponents.size()-1; c >= 0; c-- )
644 		{
645 			xpath.append( "/" ).append( pathComponents.get( c ));
646 		}
647 		
648 		if( modifier != null )
649 			modifier.afterSelector( xpath );
650 		
651 		return xpath.toString();
652 	}
653 
654 	private static int findNodeIndex(Node node)
655 	{
656 		String nm = node.getLocalName();
657 		String ns = node.getNamespaceURI();
658 		
659 		Node parentNode = node.getParentNode();
660 		if( parentNode.getNodeType() != Node.ELEMENT_NODE )
661 			return 1;
662 		
663 		NodeList nl = ((Element)parentNode).getElementsByTagNameNS( ns, nm );
664 		
665 		if( nl.getLength() == 1 )
666 			return 0;
667 		
668 		int mod = 0;
669 		for( int c = 0; c < nl.getLength(); c++ )
670 		{
671 			if( nl.item( c ).getParentNode() != node.getParentNode() )
672 				mod++;
673 			else if( nl.item( c ) == node )
674 				return c+1-mod;
675 		}
676 		
677 		throw new RuntimeException( "Child node not found in parent!?" );
678 	}
679 
680 	public static boolean setNodeValue( Node domNode, String string )
681 	{
682 		short nodeType = domNode.getNodeType();
683 		if( nodeType == Node.ELEMENT_NODE )
684 		{
685 			setElementText( ( Element ) domNode, string );
686 			return true;
687 		}
688 		else if( nodeType == Node.ATTRIBUTE_NODE || nodeType == Node.TEXT_NODE )
689 		{
690 			domNode.setNodeValue( string );
691 			return true;
692 		}
693 		
694 		return false;
695 	}
696 
697 	public static String declareXPathNamespaces( XmlObject xmlObject )
698 	{
699 		Map<QName,String> map = new HashMap<QName,String>();
700 		XmlCursor cursor = xmlObject.newCursor();
701 		
702 		while( cursor.hasNextToken() )
703 		{
704 			if( cursor.toNextToken().isNamespace() )
705 				map.put( cursor.getName(), cursor.getTextValue() );
706 		}
707 		
708 		Iterator<QName> i = map.keySet().iterator();
709 		int nsCnt = 0;
710 		
711 		StringBuffer buf = new StringBuffer();
712 		Set<String> prefixes = new HashSet<String>();
713 		Set<String> usedPrefixes = new HashSet<String>();
714 		
715 		while( i.hasNext() )
716 		{
717 			QName name = i.next();
718 			String prefix = name.getLocalPart();
719 			if( prefix.length() == 0 ) prefix = "ns" + Integer.toString( ++nsCnt );
720 			else if( prefix.equals( "xsd") || prefix.equals( "xsi")) continue;
721 			
722 			if( usedPrefixes.contains( prefix ))
723 			{
724 				int c = 1;
725 				while( usedPrefixes.contains( prefix + c )) c++;
726 				
727 				prefix = prefix + Integer.toString( c );
728 			}
729 			else prefixes.add( prefix );
730 			
731 			buf.append( "declare namespace " );
732 			buf.append( prefix );
733 			buf.append( "='" );
734 			buf.append( map.get( name ));
735 			buf.append( "';\n");
736 			
737 			usedPrefixes.add( prefix );
738 		}
739 		
740 		return buf.toString();
741 	}
742 
743 	public static String setXPathContent( String emptyResponse, String string, String actor )
744 	{
745 		try
746 		{
747 			XmlObject xmlObject = XmlObject.Factory.parse( emptyResponse );
748 			
749 			String namespaces = declareXPathNamespaces( xmlObject );
750 			if( namespaces != null && namespaces.trim().length() > 0 )
751 				string = namespaces + string;
752 			
753 			XmlObject[] path = xmlObject.selectPath( string );
754 			for( XmlObject xml : path )
755 			{
756 				setNodeValue( xml.getDomNode(), actor );
757 			}
758 			
759 			return xmlObject.toString();
760 		}
761 		catch( Exception e )
762 		{
763 			SoapUI.logError( e );
764 		}
765 		
766 		return emptyResponse;
767 	}
768 	
769 	public static QName getQName( Node node )
770 	{
771 		if( node.getNamespaceURI() == null )
772 			return new QName( node.getNodeName());
773 		else
774 			return new QName( node.getNamespaceURI(), node.getLocalName() );
775 	}
776 
777 	public static String removeXPathNamespaceDeclarations( String xpath )
778 	{
779 		while( xpath.startsWith( "declare namespace" ))
780 		{
781 			int ix = xpath.indexOf( ';' );
782 			if( ix == -1 )
783 				break;
784 			
785 			xpath = xpath.substring( ix+1 ).trim();
786 		}
787 		return xpath;
788 	}
789 
790 	public static String stripWhitespaces( String content )
791 	{
792 		try
793 		{
794 			XmlObject xml = XmlObject.Factory.parse( content, new XmlOptions().setLoadStripWhitespace().setLoadStripComments() );
795 			content = xml.xmlText();
796 		}
797 		catch( Exception e )
798 		{
799 			SoapUI.logError( e );
800 		}
801 		
802 		return content;
803 	}
804 
805 	public static NodeList getChildElements( Element elm )
806 	{
807 		List<Element> list = new ArrayList<Element>();
808 		
809 		NodeList nl = elm.getChildNodes();
810 		for( int c = 0; c < nl.getLength(); c++ )
811 		{
812 			if( nl.item( c ).getNodeType() == Node.ELEMENT_NODE )
813 				list.add(  ( Element ) nl.item( c ) );
814 		}
815 		
816 		return new ElementNodeList( list );
817 	}
818 
819 	private final static class ElementNodeList implements NodeList
820 	{
821 		private final List<Element> list;
822 
823 		public ElementNodeList( List<Element> list )
824 		{
825 			this.list = list;
826 		}
827 
828 		public int getLength()
829 		{
830 			return list.size();
831 		}
832 
833 		public Node item( int index )
834 		{
835 			return list.get( index );
836 		}}
837 
838 	public static boolean seemsToBeXml( String str )
839 	{
840 		try
841 		{
842 			return str != null && XmlObject.Factory.parse( str ) != null;
843 		}
844 		catch( Exception e )
845 		{
846 			return false;
847 		}
848 	}
849 
850 	public static String extractNamespaces( String xpath )
851 	{
852 		String result = xpath;
853 		int ix = xpath.lastIndexOf( "declare namespace" );
854 		if( ix != -1 )
855 		{
856 			ix = xpath.indexOf( '\'', ix+1 );
857 			if( ix != -1 )
858 			{
859 				ix = xpath.indexOf( '\'', ix+1 );
860 				if( ix != -1 )
861 				{
862 					ix = xpath.indexOf( ';' );
863 					if( ix != -1 )
864 					{
865 						result = xpath.substring( 0, ix+1 );
866 					}
867 				}
868 			}
869 		}
870 		
871 		return result;
872 	}
873 }
874