View Javadoc

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