Search code examples
androidxmlsoapksoap2

Adding XML file to a SOAP request


(i'm trying to say hello, but the site keeps deleting it oO)... ! Here is my question : I found out how to send a request to a webservice using ksoap, but i still cannot figure out where to add my XML to the request ! Here is my code :

    public static SoapObject soap () throws IOException, XmlPullParserException {
    SoapObject request = new SoapObject (NAMESPACE, METHOD_NAME);

    /* HERE IS THE PROBLEM */
    request.addProperty(toto, HERE IS MY XML);

    SoapSerializationEnvelope envelope = new SoapSerializationEnvelope (
            SoapEnvelope.VER11);
    envelope.setOutputSoapObject (request);
    HttpTransportSE androidHttpTransport = new HttpTransportSE (URL);
    androidHttpTransport.debug = true; 
    androidHttpTransport.call (SOAP_ACTION, envelope);
    SoapObject soapResult = (SoapObject) envelope.getResponse ();
    return soapResult;
}

If i delete the "request.addProperty line", it reaches the server, but it does nothing, because i need to send my XML. If someone know how to do that, it would definitely make my day !!

Thanks you for reading this !


Solution

  • Maybe it doesn't help you with this particular issue, but I would not recommended using ksoap. I wasted so much time getting it to work and after that I wrote my SOAP client with few hours and it works without problem.

    It's easy:

    public static HashMap<String, Object> callSOAPServer(StringBuffer soap /* YOUR XML GOES HERE*/,String action) {
        HashMap<String, Object> xMap = new HashMap<String, Object>(); 
        byte[] result = null;              
        byte[] data = new byte[1024*1024];  
        HttpClient httpclient = new DefaultHttpClient(); /* Your probably need to edit client for your needs, like timeout, scheme, etc */
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        DataInputStream is = null;
        boolean download = true;
        HttpPost httppost = new HttpPost(/* YOUR URL GOES HERE */ );
        httppost.setHeader("soapaction", action);
        httppost.setHeader("Content-Type", "text/xml; charset=utf-8");     
        try {               
             HttpEntity entity = new StringEntity(soap.toString(),HTTP.UTF_8);
             httppost.setEntity(entity);  
             HttpResponse response = httpclient.execute(httppost);
             HttpEntity r_entity = response.getEntity();
             if (r_entity != null) {                    
                 result = new byte[(int) r_entity.getContentLength()];      
                 size = result.length;                 
                 if (r_entity.isStreaming()) {                      
                    is = new DataInputStream(r_entity.getContent());     
                    while((count = is.read(data, 0, data.length)) != -1) {                      
                            buffer.write(data, 0, count);
                            total +=count;                    
                        }
                 }
                 buffer.flush();
                 result = buffer.toByteArray();
                 data = null;
                 buffer = null;                
              }             
         } catch (Exception e) {
                 e.printStackTrace();
                result = null;
         }          
         if(result !=null){             
            try {
                String sb;
                String sn;              
                sb = new String(result, "UTF-8");
                sn = sb.replace("&amp;", "AMP"); //Precaution for SAX parser
                result = sn.getBytes();     
            } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
            } 
                xMap.put(STATUS, "OK");
                xMap.put(SOAP, result);        
            }else{
                if(xMap.get(STATUS) == null) {
                    xMap.put(STATUS, "ERROR");
                }   
            }           
            httpclient.getConnectionManager().shutdown(); 
            return xMap;        
      }
    

    Here is parser:

    public ArrayList< HashMap<String,String>> parseSoap (byte[] soapResult,String soapFunctionName, String... args) {       
            ArrayList< HashMap<String,String>> xMap = new ArrayList< HashMap<String,String>>();         
            if(soapResult == null) xMap.put(STATUS, "Where is stuff to handle");
            byte[] initReqrepsonse = soapResult;
            ByteArrayInputStream bais = new ByteArrayInputStream(initReqrepsonse);
    
            SAXParserFactory spf = SAXParserFactory.newInstance();
            try {
                SAXParser sp = spf.newSAXParser();
                XMLReader xr = sp.getXMLReader();
    
                if(soapFunctionName.equals(NEWS)) { /*IF YOU USE MULTIPLE SOAP FUNCTION, YOU NEED TO DETERMINE WHICH IS WHICH...*/
                   NewsXMLHandler myXMLHandler = new NewsXMLHandler(); /*..BECAUSE HERE YOU NEED TO SPECIFY FIELDS WHICH YOU WANT TO RETRIEVE FROM XML*/
                   xr.setContentHandler(myXMLHandler);
                   xr.parse(new InputSource(bais));
                   xMap.put(SOAP_OUTPUT, myXMLHandler.getOutput());
                   myXMLHandler = null;
                 }
                 sp = null;
                 xr = null;
                 } catch (Exception e) {
                    e.printStackTrace();
                 }
              spf = null;
          return xMap;
     }
    

    And for that thing (NewsXMLHandler) which determines which fields you want to parse:

    public class NewsXMLHandler extends DefaultHandler {
    
    public NewsXMLHandler() {}
    
    private ArrayList< HashMap<String,String> > data;   
    
    private HashMap<String,String> dataHash;
    
    private final StringBuilder mStringBuilder = new StringBuilder();
    
    private boolean bStore = false;
    
    ArrayList< HashMap<String,String>>  getOutput() {
        return data;
    }
    
    
    @Override
    public void startDocument() throws SAXException 
    {
        data = new ArrayList< HashMap<String,String> >();
    
    }
    
    @Override
    public void endDocument() throws SAXException
    {
    
    }
    
    @Override
    public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
        mStringBuilder.setLength(0);
        bStore = true;      
        try { 
            //HERE YOU NEED TO SPECIFY WHICH IS ROOT NODE OF XML FROM SOAP, IN MY EXPERIENCE ITS OUT
              if(localName.equalsIgnoreCase("out")) {
                 dataHash = new HashMap<String,String>();
             }          
    
        } catch (Exception e) 
        {
            Log.d("error in startElement", e.getStackTrace().toString());
        }
    }
    @Override
    
    public void endElement(String namespaceURI, String localName, String qName) throws SAXException 
    {
            bStore = false;         
    
            //HERE IT IS, JUST WRITE NAME OF NODE WHICH YOU WANT TO USE FOR YOUR APPLICATION        
            if (localName.equalsIgnoreCase("your node name"))
            {               
                dataHash.put("your node name", mStringBuilder.toString().trim());           
            }
    
            if (localName.equalsIgnoreCase("your node name 2"))
            {               
                dataHash.put("your node name 2", mStringBuilder.toString().trim());         
            }
    
            // CONTINUE WITH THOSE IFS UNTIL YOU HAVE ALL FIELDS WHICH YOU NEED COVERED
    
            // HERE YOU WRAP ALL OF THOSE HIGHER NODE AND SAVE TO ARRAYLIST, SO IF THERE ARE MORE OF THEM, YOU GET THEM ALL - AGAIN ITS NAME OF ROOT NODE 
            if(localName.equalsIgnoreCase("out")) {
                data.add(dataHash);
                dataHash = null;
            } 
    
    }
    @Override
    
    public void characters(char ch[], int start, int length)
    {
    
        if (bStore) 
        {   
            mStringBuilder.append(ch, start, length);
            if(mStringBuilder.length() == 0)  mStringBuilder.setLength(0);            
    
        }
    }
    }
    

    And here goes the usage. As it seems you alredy figured out, you can't execute URL request on main thread. You just need to use AsyncTask, Service, IntentService, etc. I am not going to cover it here. I like to use IntentService and save entries to database.

    So lets say, you wrap those two static function in class SOAPHandler:

    HashMap<String, Object> SOAPResponse = SOAPHandler.callSOAPSERVER(/*YOUR XML REQUEST HERE*/, /*NAME OF SOAP METHOD ON SERVER*/)
    ArrayList< HashMap<String,String>> parsedEntries = SOAPHandler.parseSoap(SOAPResponse, NEWS, NULL);
    
    foreach(HashMap<String,String> hash : parsedEntries) {
           String entryOne = hash.get("your node name");
           String entryTwo = hash.get("your node name 2");
           //HERE YOU HAVE YOUR STRINGS, DO WHATEVER WITH THEM
    }