How to parse the SOAP response with complex objects in Android
Android :: Ksoap2 Kullanarak Webservislere Erişme yazımda Android üzerinden webservislerin nasıl çağrılacağı hakkında bir şeyler yazmıştım. Oradaki örnekte gelen yanıtın derinliği 1’di ve parse edilecek tüm değerler aynı seviyede property’ler olarak gelmişti.
Eğer iç içe yapıda bir yanıt gelirse ya da gelen yanıt bir obje listesi olursa ve listenin boyutu önceden belli değilse ilk örneğimizdeki kod yetersiz kalacaktır. Bu gibi durumlarda ne yapmak gerektiğini bir örnekle inceleyelim.
Öncelikle uygun bir public webservis arayıp bulmak zor geldi, kendi webservisimi yazdım. Örnek olarak bir şirketin çalışanlarının listesini bize döndürsün, biz de onu Android’den çağırıp parse edelim yeterli diye düşündüm. Listesi dönecek olan çalışanları tutacak Employee classı aşağıdaki gibi:
public class Employee { private int id; private String name; private String surName; private String department; private Double salary; public Employee() { super(); } public Employee(int id, String name, String surName, String department, Double salary) { super(); this.id = id; this.name = name; this.surName = surName; this.department = department; this.salary = salary; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSurName() { return surName; } public void setSurName(String surName) { this.surName = surName; } public String getDepartment() { return department; } public void setDepartment(String department) { this.department = department; } public Double getSalary() { return salary; } public void setSalary(Double salary) { this.salary = salary; } @Override public String toString() { return "Employee [id=" + id + ", name=" + name + ", surName=" + surName + ", department=" + department + ", salary=" + salary + "]"; } }
Çağırdığımızda bize bu classtan oluşmuş nesnelerin biz listesini döndürecek servis metodunu da burada göstermek istersek:
public class ComplexWebserviceDemo implements Serializable { private static final long serialVersionUID = 8058591245625624821L; public Employee[] getEmployeeList() { try { Employee[] array = new Employee[5]; array [0] = new Employee(1, "F. Oğuz", "ÖZKEROĞLU", "Yazılım", 0.0); array [1] = new Employee(2, "Ad1", "Soyad1", "Yazılım", 1000.0); array [2] = new Employee(3, "Ad2", "Soyad2", "Arge", 2000.0); array [3] = new Employee(4, "Ad3", "Soyad3", "Muhasebe", 1000.0); array [4] = new Employee(5, "Ad4", "Soyad4", "Yazılım", 750.0); return array; } catch (Exception e) { e.printStackTrace(); return null; } } }
Metodun içinde sanki database’den veri çekiyormuşuz gibi olayı simule edip elle birkaç veri ekliyoruz. Bu arada yazılım departmanının maaş ortalamasının düşüklüğüne de dikkat çekmiş olalım :)
Sıra geldi servisi çağırmaya.. Parametre almayan getEmployeeList() metodunu çağırdığımızda aşağıdaki SOAP response bize geri dönecektir.
<?xml version="1.0" encoding="utf-8"?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <soapenv:Body> <getEmployeeListResponse xmlns="http://demo.webservice.ozkeroglu.com"> <getEmployeeListReturn> <employee> <employee> <department>Yazılım</department> <id>1</id> <name>F. Oğuz</name> <salary>0.0</salary> <surName>ÖZKEROĞLU</surName> </employee> <employee> <department>Yazılım</department> <id>2</id> <name>Ad1</name> <salary>1000.0</salary> <surName>Soyad1</surName> </employee> <employee> <department>Arge</department> <id>3</id> <name>Ad2</name> <salary>2000.0</salary> <surName>Soyad2</surName> </employee> <employee> <department>Muhasebe</department> <id>4</id> <name>Ad3</name> <salary>1000.0</salary> <surName>Soyad3</surName> </employee> <employee> <department>Yazılım</department> <id>5</id> <name>Ad4</name> <salary>750.0</salary> <surName>Soyad4</surName> </employee> </employee> </getEmployeeListReturn> </getEmployeeListResponse> </soapenv:Body> </soapenv:Envelope>
Burada ksoap2’nin bize vereceği response, getEmployeeListReturn node’una karşılık gelecektir. Onun altında employee isminde bir node var. Bu da servisten gelen Employee listesine karşılık geliyor. Onun altında da her bir çalışan için yine employee isminde bir node var ve her bir employee için id, name, surName, department ve salary değerleri bulunmaktadır.
Böyle bir durumda şu gibi bir strateji izlenebilir: İlk adımda gelen response zaten bir SoapObject olarak elimizde var. Bu SoapObject nesnesinin içinde 1 tane de employee listesini karşılayan property var. Bu property’e ya ismi ile (employee) ya da bulunduğu indexi ile (0) erişip onu da SoapObject olarak alacağız. Daha sonra elimizdeki yeni SoapObject (employee listesi)’ne bakıyoruz ve içinde hala objeler olduğunu görüyoruz. Onlara da ulaşmak için bir döngüde listenin boyutu kadar defa dönüp, her bir elamanı yeniden bir SoapObject olarak alıp, ondan sonra parse edip kullanmamız gerekecek.
Bunu yapacak metodu barındıran class da aşağıdaki gibi olabilir:
public class WebserviceClient { private static final String METHOD_NAME = "getEmployeeList"; private static final String NAMESPACE = "http://demo.webservice.ozkeroglu.com"; private static final String SOAP_ACTION = ""; private static final String URL = "http://192.168.1.2:8080/ComplexTypeWebServiceDemo/services/ComplexWebserviceDemo?wsdl"; public static List<Employee> getEmployeeList() { List<Employee> list = null; SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME); SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); envelope.setOutputSoapObject(request); HttpTransportSE androidHttpTransport = new HttpTransportSE(URL); androidHttpTransport.debug = true; try { androidHttpTransport.call(SOAP_ACTION, envelope); SoapObject response = (SoapObject) envelope.getResponse(); if (response.toString().equals("anyType{}") || response == null) { list = null; } else { SoapObject soapEmployeeList = (SoapObject) response.getProperty("employee"); // ya da // SoapObject soapEmployeeList = (SoapObject) response.getProperty(0); list = new ArrayList<Employee>(); int employeeCount = soapEmployeeList.getPropertyCount(); for (int i = 0; i < employeeCount; i++) { Employee item = new Employee(); SoapObject soapEmployee = (SoapObject) soapEmployeeList.getProperty(i); if (soapEmployee.hasProperty("id")) { item.setId(Integer.parseInt(soapEmployee.getPropertyAsString("id"))); } if (soapEmployee.hasProperty("name")) { item.setName(soapEmployee.getPropertyAsString("name")); } if (soapEmployee.hasProperty("surName")) { item.setSurName(soapEmployee.getPropertyAsString("surName")); } if (soapEmployee.hasProperty("department")) { item.setDepartment(soapEmployee.getPropertyAsString("department")); } if (soapEmployee.hasProperty("name")) { item.setSalary(Double.parseDouble(soapEmployee.getPropertyAsString("salary"))); } list.add(item); } } } catch (Exception e) { e.printStackTrace(); list = null; } return list; } }
SoapObject.getPropertyCount() metodu bize o SoapObject’in kaç tane özelliği olduğu bilgisini vermektedir. Servisin liste döndürdüğü ve liste boyutunun değişken olduğu durumlarda, döngüdeki iterasyon sayısını belirlemede oldukça kullanışlı bir metod olacaktır.
Test için şu metodu kullandığımda:
private void invokeService() { List<Employee> employeeList = WebserviceClient.getEmployeeList(); for (Employee employee : employeeList) { System.out.println(employee); } }
Console çıktısı aşağıdaki gibi oldu:
Employee [id=1, name=F. Oguz, surName=ÖZKEROGLU, department=Yazilim, salary=0.0]
Employee [id=2, name=Ad1, surName=Soyad1, department=Yazilim, salary=1000.0]
Employee [id=3, name=Ad2, surName=Soyad2, department=Arge, salary=2000.0]
Employee [id=4, name=Ad3, surName=Soyad3, department=Muhasebe, salary=1000.0]
Employee [id=5, name=Ad4, surName=Soyad4, department=Yazilim, salary=750.0]
Umarım faydalı bir yazı olmuştur.
Android :: Webservisten Dönen İç İçe Yapıdaki XML’in Parse Edilmesi
hocam bu sistemin hazır çalışan bir kodları varmı birçok kez web service için yazılmış örneklere baktım hiçbiri çalıştıramadım. Çalışan bir kod var ise burdan veya mail atabilirseniz cok makbule gececek.
teşekkür ederim.Çalışmaşarınızın devamını dilerim
@hasan
Şu anda askerlik görevimi yapmak üzere Adana’da bulunuyorum, bir 5 ay kadar daha kodlara ben de ulaşamayacağım maalesef.
Kardeşim eyvallah emeğine sağlık, çok güzel yazı olmuş. Fakat sana bu noktada bir soru sormam lazım. Web Servisten gelen liste şu şekilde;
ANKARA
ANTALYA
Bu durumda nasıl alacağım verileri ??
//
// ANKARA
//
//
// ANTALYA
//
@Serif Sadi
Wordpress yorumları HTML olarak aldığı için gönderdiğin XML’ler tam çıkmamış. Acaba yorumunu
arasına, şu … olan kısımların yerine yazıp yeniden yollayabilir misin?
İyi günler,
Paylaşımınız için teşekkür ederim. Detaylı inceleme yapabilmem için proje dosyasını göndermeniz mümkün mü ?
İyi çalışmalar.
Sizin kodlarınızı kullanarak webservisi değiştirerek yaptığım uygulama çalışmıyor direkt olarak kapatıyor. Database deki tablomda bulunan User verilerini web servis aracılığı ile xml olarak çekip listview de göstermek istiyorum. Ancak bir türlü olmadı. Çalışır vaziyette bu şekilde işlem yapan uygulamanız var mı test edebileceğim.
Selamlar , bende hasProperty ve getPropertyAsString özellikleri kullnılmıyor üzeri kırmızı sebebi ne olabilir.