You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android中如何手动将SOAP XML响应转换为Java对象?

手动解析ONVIF SOAP XML响应到Java对象(Android AOSP环境)

既然Android AOSP不包含JAX-WS和JAXB,手动解析确实是唯一可行的方案。针对你提到的ONVIF GetSystemDateAndTime SOAP响应,我来分享一套实用的实现步骤和代码示例:

首先,先补全你给出的SOAP响应片段(符合ONVIF标准格式),方便后续解析参考:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:tds="http://www.onvif.org/ver10/device/wsdl">
  <SOAP-ENV:Body>
    <tds:GetSystemDateAndTimeResponse>
      <tds:SystemDateAndTime>
        <tds:DateTimeType>NTP</tds:DateTimeType>
        <tds:DaylightSavings>true</tds:DaylightSavings>
        <tds:TimeZone>
          <tds:TZ>CST-8</tds:TZ>
        </tds:TimeZone>
        <tds:UTCDateTime>
          <tds:Date>
            <tds:Year>2024</tds:Year>
            <tds:Month>5</tds:Month>
            <tds:Day>20</tds:Day>
          </tds:Date>
          <tds:Time>
            <tds:Hour>10</tds:Hour>
            <tds:Minute>30</tds:Minute>
            <tds:Second>45</tds:Second>
          </tds:Time>
        </tds:UTCDateTime>
        <tds:LocalDateTime>
          <tds:Date>
            <tds:Year>2024</tds:Year>
            <tds:Month>5</tds:Month>
            <tds:Day>20</tds:Day>
          </tds:Date>
          <tds:Time>
            <tds:Hour>18</tds:Hour>
            <tds:Minute>30</tds:Minute>
            <tds:Second>45</tds:Second>
          </tds:Time>
        </tds:LocalDateTime>
      </tds:SystemDateAndTime>
    </tds:GetSystemDateAndTimeResponse>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

第一步:定义对应的数据模型类

我们需要创建和SOAP响应结构匹配的Java类,用来存储解析后的数据:

public class SystemDateTime {
    private String dateTimeType;
    private boolean daylightSavings;
    private TimeZone timeZone;
    private DateTime utcDateTime;
    private DateTime localDateTime;

    // Getters & Setters
    public String getDateTimeType() { return dateTimeType; }
    public void setDateTimeType(String dateTimeType) { this.dateTimeType = dateTimeType; }
    public boolean isDaylightSavings() { return daylightSavings; }
    public void setDaylightSavings(boolean daylightSavings) { this.daylightSavings = daylightSavings; }
    public TimeZone getTimeZone() { return timeZone; }
    public void setTimeZone(TimeZone timeZone) { this.timeZone = timeZone; }
    public DateTime getUtcDateTime() { return utcDateTime; }
    public void setUtcDateTime(DateTime utcDateTime) { this.utcDateTime = utcDateTime; }
    public DateTime getLocalDateTime() { return localDateTime; }
    public void setLocalDateTime(DateTime localDateTime) { this.localDateTime = localDateTime; }

    // 时区内部类
    public static class TimeZone {
        private String tz;

        public String getTz() { return tz; }
        public void setTz(String tz) { this.tz = tz; }
    }

    // 日期时间内部类
    public static class DateTime {
        private Date date;
        private Time time;

        public Date getDate() { return date; }
        public void setDate(Date date) { this.date = date; }
        public Time getTime() { return time; }
        public void setTime(Time time) { this.time = time; }

        // 日期子内部类
        public static class Date {
            private int year;
            private int month;
            private int day;

            public int getYear() { return year; }
            public void setYear(int year) { this.year = year; }
            public int getMonth() { return month; }
            public void setMonth(int month) { this.month = month; }
            public int getDay() { return day; }
            public void setDay(int day) { this.day = day; }
        }

        // 时间子内部类
        public static class Time {
            private int hour;
            private int minute;
            private int second;

            public int getHour() { return hour; }
            public void setHour(int hour) { this.hour = hour; }
            public int getMinute() { return minute; }
            public void setMinute(int minute) { this.minute = minute; }
            public int getSecond() { return second; }
            public void setSecond(int second) { this.second = second; }
        }
    }
}

第二步:用XmlPullParser实现解析逻辑

Android AOSP原生支持XmlPullParser,它是轻量高效的XML解析器,非常适合这种场景:

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

import java.io.IOException;
import java.io.InputStream;

public class SoapResponseParser {

    public static SystemDateTime parseGetSystemDateAndTimeResponse(InputStream inputStream) throws XmlPullParserException, IOException {
        XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
        XmlPullParser parser = factory.newPullParser();
        parser.setInput(inputStream, "UTF-8");

        int eventType = parser.getEventType();
        SystemDateTime systemDateTime = null;
        SystemDateTime.TimeZone timeZone = null;
        SystemDateTime.DateTime utcDateTime = null;
        SystemDateTime.DateTime localDateTime = null;
        SystemDateTime.DateTime.Date date = null;
        SystemDateTime.DateTime.Time time = null;

        while (eventType != XmlPullParser.END_DOCUMENT) {
            String tagName = parser.getName();
            String namespace = parser.getNamespace();
            final String ONVIF_DEVICE_NAMESPACE = "http://www.onvif.org/ver10/device/wsdl";

            switch (eventType) {
                case XmlPullParser.START_TAG:
                    // 用命名空间判断更可靠,避免前缀变化影响解析
                    if (ONVIF_DEVICE_NAMESPACE.equals(namespace)) {
                        switch (tagName) {
                            case "SystemDateAndTime":
                                systemDateTime = new SystemDateTime();
                                break;
                            case "DateTimeType":
                                if (systemDateTime != null) {
                                    systemDateTime.setDateTimeType(parser.nextText().trim());
                                }
                                break;
                            case "DaylightSavings":
                                if (systemDateTime != null) {
                                    systemDateTime.setDaylightSavings(Boolean.parseBoolean(parser.nextText().trim()));
                                }
                                break;
                            case "TimeZone":
                                timeZone = new SystemDateTime.TimeZone();
                                break;
                            case "TZ":
                                if (timeZone != null && systemDateTime != null) {
                                    timeZone.setTz(parser.nextText().trim());
                                    systemDateTime.setTimeZone(timeZone);
                                }
                                break;
                            case "UTCDateTime":
                                utcDateTime = new SystemDateTime.DateTime();
                                break;
                            case "LocalDateTime":
                                localDateTime = new SystemDateTime.DateTime();
                                break;
                            case "Date":
                                date = new SystemDateTime.DateTime.Date();
                                break;
                            case "Year":
                                if (date != null) {
                                    date.setYear(Integer.parseInt(parser.nextText().trim()));
                                }
                                break;
                            case "Month":
                                if (date != null) {
                                    date.setMonth(Integer.parseInt(parser.nextText().trim()));
                                }
                                break;
                            case "Day":
                                if (date != null) {
                                    date.setDay(Integer.parseInt(parser.nextText().trim()));
                                    // 将日期关联到当前的DateTime对象
                                    if (utcDateTime != null && utcDateTime.getDate() == null) {
                                        utcDateTime.setDate(date);
                                    } else if (localDateTime != null && localDateTime.getDate() == null) {
                                        localDateTime.setDate(date);
                                    }
                                }
                                break;
                            case "Time":
                                time = new SystemDateTime.DateTime.Time();
                                break;
                            case "Hour":
                                if (time != null) {
                                    time.setHour(Integer.parseInt(parser.nextText().trim()));
                                }
                                break;
                            case "Minute":
                                if (time != null) {
                                    time.setMinute(Integer.parseInt(parser.nextText().trim()));
                                }
                                break;
                            case "Second":
                                if (time != null) {
                                    time.setSecond(Integer.parseInt(parser.nextText().trim()));
                                    // 将时间关联到当前的DateTime对象
                                    if (utcDateTime != null && utcDateTime.getTime() == null) {
                                        utcDateTime.setTime(time);
                                    } else if (localDateTime != null && localDateTime.getTime() == null) {
                                        localDateTime.setTime(time);
                                    }
                                }
                                break;
                        }
                    }
                    break;
                case XmlPullParser.END_TAG:
                    if (ONVIF_DEVICE_NAMESPACE.equals(namespace)) {
                        switch (tagName) {
                            case "UTCDateTime":
                                if (systemDateTime != null) {
                                    systemDateTime.setUtcDateTime(utcDateTime);
                                }
                                break;
                            case "LocalDateTime":
                                if (systemDateTime != null) {
                                    systemDateTime.setLocalDateTime(localDateTime);
                                }
                                break;
                        }
                    }
                    break;
            }
            eventType = parser.next();
        }
        return systemDateTime;
    }
}

一些关键注意事项

  • 命名空间判断:上面的代码使用了ONVIF设备服务的命名空间来判断标签,比直接匹配带前缀的标签更可靠,因为有些设备可能会用不同的前缀(比如dev代替tds)
  • 异常处理:在AOSP环境中,要确保捕获IOException和XmlPullParserException,避免未处理的异常导致进程崩溃
  • 扩展性:如果需要解析其他ONVIF SOAP响应,可以复用这套结构:先定义对应的数据类,再扩展解析逻辑中的标签判断分支
  • 测试验证:可以用模拟的SOAP响应输入流来测试解析逻辑,确保所有字段都能正确映射

内容的提问来源于stack exchange,提问作者kiran Biradar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:53:40