【安卓】解析XML格式数据

这里需要搭建一个Web服务器,在这个服务器上提供一段XML文本,然后在程序里去访问这个服务器,再对得到的XML文本进行解析。首先需要下载一个Apache服务器的安装包,官方下载地址是:http://httpd.apache.org。然后一直点击"Next",会提示让你输入自己的域名,我们随便填一个域名就可以了。之后继续点击"Next"就可以完成安装了,安装成功后服务器会自动启动。接下来进入安装位置的htdocs目录下,在这里新建一个名为get_data.xml的文件,然后编辑这个文件,并加入如下XML格式的内容。

xml 复制代码
<apps>
 <app>
 <id>1</id>
 <name>Google Maps</name>
 <version>1.0</version>
 </app>
 <app>
 <id>2</id>
 <name>Chrome</name>
 <version>2.1</version>
 </app>
 <app>
 <id>3</id>
 <name>Google Play</name>
 <version>2.3</version>
 </app>
</apps>

这时在浏览器中访问http://127.0.0.1/get_data.xml这个网址访问到。

Pull解析方式

修改MainActivity中的代码。

java 复制代码
public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    TextView responseText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button sendRequest = (Button) findViewById(R.id.sendRequestBtn);
        responseText = (TextView) findViewById(R.id.responseText);
        sendRequest.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.sendRequestBtn) {
//            sendRequestWithHttpURLConnection();
            sendRequestWithOkHttp();
        }
    }

    private void sendRequestWithOkHttp() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    OkHttpClient client = new OkHttpClient();
                    Request request = new Request.Builder()
//                            .url("https://www.baidu.com")
                            .url("http://10.0.2.2/get_data.xml")
                            .build();
                    Response response = client.newCall(request).execute();
                    String responseData = response.body().string();
//                    showResponse(responseData);
                    parseXMLWithPull(responseData);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    private void parseXMLWithPull(String xmlData) {
        try {
            XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
            XmlPullParser xmlPullParser = factory.newPullParser();
            xmlPullParser.setInput(new StringReader(xmlData));
            int eventType = xmlPullParser.getEventType();
            String id = "";
            String name = "";
            String version = "";
            while (eventType != XmlPullParser.END_DOCUMENT) {
                String nodeName = xmlPullParser.getName();
                switch (eventType) {
                    // 开始解析某个节点
                    case XmlPullParser.START_TAG: {
                        if ("id".equals(nodeName)) {
                            id = xmlPullParser.nextText();
                        } else if ("name".equals(nodeName)) {
                            version = xmlPullParser.nextText();
                        }
                        break;
                    }
                    // 完成解析某个节点
                    case XmlPullParser.END_TAG: {
                        if ("app".equals(nodeName)) {
                            Log.d("MainActivity", "id is " + id);
                            Log.d("MainActivity", "name is " + name);
                            Log.d("MainActivity", "version is " + version);
                        }
                        break;
                    }
                    default:
                        break;
                }
                eventType = xmlPullParser.next();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void sendRequestWithHttpURLConnection() {
        // 开启线程来发起网络请求
        new Thread(new Runnable() {
            @Override
            public void run() {
                HttpURLConnection connection = null;
                BufferedReader reader = null;
                try {
                    URL url = new URL("https://www.baidu.com");
                    connection = (HttpURLConnection) url.openConnection();
                    connection.setRequestMethod("GET");
                    connection.setConnectTimeout(8000);
                    connection.setReadTimeout(8000);
                    InputStream in = connection.getInputStream();
                    // 下面对获取到的输入流进行读取
                    reader = new BufferedReader(new InputStreamReader(in));
                    StringBuilder response = new StringBuilder();
                    String line;
                    while ((line = reader.readLine()) != null) {
                        response.append(line);
                    }
                    showResponse(response.toString());
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if (reader != null) {
                        try {
                            reader.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    if (connection != null) {
                        connection.disconnect();
                    }
                }
            }
        }).start();
    }

    private void showResponse(final String response) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                // 在这里进行UI操作,将结果显示到界面上
                responseText.setText(response);
            }
        });
    }
}

将HTTP请求的地址改成了http://10.0.2.2/get_data.xml,10.0.2.2对于模拟器来说就是计算机本机的IP地址。在得到了服务器返回的数据后,调用parseXMLWithPull()方法来解析服务器返回的数据。

从Android9.0系统开始,应用程序默认只允许使用HTTPS类型的网络请求,HTTP类型的网络请求因为有安全隐患默认不再被支持,而Apache服务器现在使用的就是HTTP。

为了能让程序使用HTTP需要进行配置。右击res目录→New→Directory,创建一个xml目录,接着右击xml目录→New→File,创建一个network_config.xml文件。然后修改network_config.xml文件中的内容。

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
 <base-config cleartextTrafficPermitted="true">
 <trust-anchors>
 <certificates src="system" />
 </trust-anchors>
 </base-config>
</network-security-config>

这段配置文件的意思就是允许我们以明文的方式在网络上传输数据,而HTTP使用的就是明文传输方式。

接下来修改AndroidManifest.xml中的代码来启用我们刚才创建的配置文件。

xml 复制代码
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
 package="com.example.networktest">
 ...
 <application
 android:allowBackup="true"
 android:icon="@mipmap/ic_launcher"
 android:label="@string/app_name"
 android:roundIcon="@mipmap/ic_launcher_round"
 android:supportsRtl="true"
 android:theme="@style/AppTheme"
 android:networkSecurityConfig="@xml/network_config">
 ...
 </application>
</manifest>

这样就可以在程序中使用HTTP了。

SAX解析方式

新建一个ContentHandler类继承自DefaultHandler,并重写父类的5个方法。

java 复制代码
public class ContentHandler extends DefaultHandler {

    private String nodeName;
    private StringBuilder id;
    private StringBuilder name;
    private StringBuilder version;

    @Override
    public void startDocument() throws SAXException {
        id = new StringBuilder();
        name = new StringBuilder();
        version = new StringBuilder();
    }

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        // 记录当前节点名
        nodeName = localName;
    }

    @Override
    public void characters(char[] ch, int start, int length) throws  SAXException {
        // 根据当前的节点名判断将内容添加到哪一个StringBuilder对象中
        if ("id".equals(nodeName)) {
            id.append(ch, start, length);
        } else if ("name".equals(nodeName)) {
            name.append(ch, start, length);
        } else if ("version".equals(nodeName)) {
            version.append(ch, start, length);
        }
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        if ("app".equals(localName)) {
            Log.d("ContentHandler", "id is " + id.toString().trim());
            Log.d("ContentHandler", "name is " + name.toString().trim());
            Log.d("ContentHandler", "version is " + version.toString().trim());
            // 最后要将StringBuilder清空掉
            id.setLength(0);
            name.setLength(0);
            version.setLength(0);
        }
    }

    @Override
    public void endDocument() throws SAXException {
        super.endDocument();
    }
}

修改MainActivity中的代码。

java 复制代码
	private void sendRequestWithOkHttp() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    OkHttpClient client = new OkHttpClient();
                    Request request = new Request.Builder()
//                            .url("https://www.baidu.com")
                            .url("http://10.0.2.2/get_data.xml")
                            .build();
                    Response response = client.newCall(request).execute();
                    String responseData = response.body().string();
//                    showResponse(responseData);
//                    parseXMLWithPull(responseData);
                    parseXMLWithSAX(responseData);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    private void parseXMLWithSAX(String xmlData) {
        try {
            SAXParserFactory factory = SAXParserFactory.newInstance();
            XMLReader xmlReader = factory.newSAXParser().getXMLReader();
            ContentHandler handler = new ContentHandler();
            // 将ContentHandler的实例设置到XMLReader中
            xmlReader.setContentHandler(handler);
            // 开始执行解析
            xmlReader.parse(new InputSource(new StringReader(xmlData)));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
相关推荐
小李不想输啦2 小时前
什么是微服务、微服务如何实现Eureka,网关是什么,nacos是什么
java·spring boot·微服务·eureka·架构
张铁铁是个小胖子2 小时前
微服务学习
java·学习·微服务
ggs_and_ddu2 小时前
Android--java实现手机亮度控制
android·java·智能手机
AITIME论道3 小时前
论文解读 | EMNLP2024 一种用于大语言模型版本更新的学习率路径切换训练范式
人工智能·深度学习·学习·机器学习·语言模型
敲代码娶不了六花4 小时前
jsp | servlet | spring forEach读取不了对象List
java·spring·servlet·tomcat·list·jsp
Yhame.4 小时前
深入理解 Java 中的 ArrayList 和 List:泛型与动态数组
java·开发语言
是小崔啊5 小时前
开源轮子 - EasyExcel02(深入实践)
java·开源·excel
mazo_command6 小时前
【MATLAB课设五子棋教程】(附源码)
开发语言·matlab
myNameGL6 小时前
linux安装idea
java·ide·intellij-idea
IT猿手6 小时前
多目标应用(一):多目标麋鹿优化算法(MOEHO)求解10个工程应用,提供完整MATLAB代码
开发语言·人工智能·算法·机器学习·matlab