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