[Android]关于使用Pull方式解析稍复杂的XML文件问题

__椎名真白 2018-03-10 10:18:20
大佬们晚上好,又是我。
这样的啊,我尝试了一下爱词霸的查词API,发现返回json数据和xml数据是不一样的。xml的数据要比json数据多了例句。
我解析过超简单的xml文件。但是这种复杂一点的完全没有头绪,弄了一天多,数据就是解析不正确。
这是内个XML文件的内容。
<?xml version="1.0" encoding="UTF-8"?>
<dict num="219" id="219" name="219">
<key>good</key>
<ps>g?d</ps>
<pron>http://res.iciba.com/resource/amp3/oxford/0/28/a2/28a24294fed307cf7e65361b8da4f6e5.mp3</pron>
<ps>ɡ?d</ps>
<pron>http://res.iciba.com/resource/amp3/1/0/75/5f/755f85c2723bb39381c7379a604160d8.mp3</pron>
<pos>adj.</pos>
<acceptation>好的;优秀的;有益的;漂亮的,健全的;
</acceptation>
<pos>n.</pos>
<acceptation>好处,利益;善良;善行;好人;
</acceptation>
<pos>adv.</pos>
<acceptation>同well;
</acceptation>
<sent>
<orig>
Best is the superlative form of good and worst is the superlative form of bad.
</orig>
<trans>
“best”是“good”的最高级形式,“worst” 是“bad”的最高级形式.
</trans>
</sent>
<sent>
<orig>
Good has captured the essence of the runaway, but does not pursue its most disturbing consequences.
</orig>
<trans>
Good抓住了这场失控的本质, 但没有进一步追踪这个事件最让人担忧的后果.
</trans>
</sent>
<sent>
<orig>
The state of the stream is revealed by the bad, fail, eof, and good operations.
</orig>
<trans>
流的状态由bad 、 fail 、 eof 和good操作提示.
</trans>
</sent>
<sent>
<orig>
Good Christian, good parent, good child, good wife, good husband.
</orig>
<trans>
虔诚的基督徒, 慈爱的父母, 孝顺的儿女, 贤良的妻子, 尽职的丈夫.
</trans>
</sent>
<sent>
<orig>
Good habits nurture good characters; good characters mold good fates.
</orig>
<trans>
好习惯育成好品格, 好品格塑造好命运.
</trans>
</sent>
</dict>

看着也不是很难。
然后我根据这个xml文件创建了一个JavaBean。如下:
package com.my.wordbar.bean;

import java.util.List;

public class JinshanEnglishToChineseBean {

private String query; //查询文本
private String enVoice; //英式发音
private String EnVoiceUrl; //英式发音地址
private String anVoice; //美式发音
private String anVoiceUrl; //美式发音地址

//因为发音为英、美两种,只要返回成功,一定会有两种发音。所以没有写成链表形式。

private List<MeanBean> meanList; //词性和解释列表
private List<Example> exampleList; //例句列表



private static class MeanBean{

private String type; //词性
private String mean; //解释

public String getType() {
return type;
}

public void setType(String type) {
this.type = type;
}

public String getMean() {
return mean;
}

public void setMean(String mean) {
this.mean = mean;
}
}

private static class Example{

private String chinese; //中文
private String english; //英文

public String getChinese() {
return chinese;
}

public void setChinese(String chinese) {
this.chinese = chinese;
}

public String getEnglish() {
return english;
}

public void setEnglish(String english) {
this.english = english;
}
}

public String getQuery() {
return query;
}

public void setQuery(String query) {
this.query = query;
}

public String getEnVoice() {
return enVoice;
}

public void setEnVoice(String enVoice) {
this.enVoice = enVoice;
}

public String getEnVoiceUrl() {
return EnVoiceUrl;
}

public void setEnVoiceUrl(String enVoiceUrl) {
EnVoiceUrl = enVoiceUrl;
}

public String getAnVoice() {
return anVoice;
}

public void setAnVoice(String anVoice) {
this.anVoice = anVoice;
}

public String getAnVoiceUrl() {
return anVoiceUrl;
}

public void setAnVoiceUrl(String anVoiceUrl) {
this.anVoiceUrl = anVoiceUrl;
}

public List<MeanBean> getMeanList() {
return meanList;
}

public void setMeanList(List<MeanBean> meanList) {
this.meanList = meanList;
}

public List<Example> getExampleList() {
return exampleList;
}

public void setExampleList(List<Example> exampleList) {
this.exampleList = exampleList;
}
}

就是getter和setter方法占地方,实际内容还是很少的。
然后开始发送网络请求,返回数据也是一点毛病没有。如下:

看这个数据是不是信心爆棚。。。然后问题就来了。。我把返回的数据字符串传入解析函数进行解析:
//使用pull方式解析XML文件
public void parseXMLWithPull(String result){

try {

XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser xmlPullParser = factory.newPullParser();
xmlPullParser.setInput(new StringReader(result));
int eventType = xmlPullParser.getEventType();

JinshanEnglishToChineseBean e2cBean = new JinshanEnglishToChineseBean();

while(eventType != XmlPullParser.END_DOCUMENT){
String nodeName = xmlPullParser.getName();
switch(eventType){
//开始解析
case XmlPullParser.START_TAG:{
if("key".equals(nodeName)){
e2cBean.setQuery(xmlPullParser.nextText());
}else if("ps".equals(nodeName)){
e2cBean.setEnVoice(xmlPullParser.nextText());
}else if("pron".equals(nodeName)){
e2cBean.setEnVoiceUrl(xmlPullParser.nextText());
}else if("ps".equals(nodeName)){
e2cBean.setAnVoice(xmlPullParser.nextText());
}else if("pron".equals(nodeName)){
e2cBean.setAnVoiceUrl(xmlPullParser.nextText());
}

//剩下的没写,解析出来的都是错的
break;
}
default:
break;
}
eventType = xmlPullParser.next();
}

TextView responseText = (TextView) findViewById(R.id.response);
responseText.setText(e2cBean.getQuery() + "---" + e2cBean.getEnVoice() + "---" + e2cBean.getEnVoiceUrl()
+ "---" + e2cBean.getAnVoice() + "---" + e2cBean.getAnVoiceUrl());

}catch(Exception e){
e.printStackTrace();
Log.d(TAG, "解析过程中出错!!!");
}

}

然后解析结果就这样了:

第二个发音和发音地址都是空的。我解析过下面的数据,解析不出来。我不知道怎么写才是正确的。
如果按照这种方式解析XML,该怎么写才是正确的。
希望大佬们不吝赐教,多看两眼,给凡人指明一条通往希望的光明道路。
给出具体解决方案,或者具体代码都可以。我还有xml数据要解析。现在没有方法。好气啊。网上的解析方法都是解析的超简单的xml数据,我上我也行啊。。。大佬们。小迷弟已经找不到人生方向了。。
...全文
382 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
jklwan 2018-03-12
  • 打赏
  • 举报
回复
没有其他的属性还算简单了,另外如果是java7可以用switch代替,比if else效率高
jklwan 2018-03-12
  • 打赏
  • 举报
回复
引用 5 楼 Lone1yCode 的回复:
对啊,debug的时候就发现它走的步骤特别多。java8就不能加switch了吗?或者我这段代码,是不是可以加一个case,如果是TAG_ENG,就跳往下一个标签。应该效率会提高一点。
java7及以后才能switch这String 加上跳往下个标签

//使用pull方式解析XML文件
    public void parseJinshanEnglishToChineseXMLWithPull(String result) {
        try {
            XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
            XmlPullParser xmlPullParser = factory.newPullParser();
            xmlPullParser.setInput(new StringReader(result));
            int eventType = xmlPullParser.getEventType();

            StringBuilder queryText = new StringBuilder();      //查询文本
            StringBuilder voiceText = new StringBuilder();      //发音和发音地址信息
            StringBuilder meanText = new StringBuilder();       //基本释义信息
            StringBuilder exampleText = new StringBuilder();    //例句信息

            while (eventType != XmlPullParser.END_DOCUMENT) {
                String nodeName = xmlPullParser.getName();
                switch (eventType) {
                    //开始解析
                    case XmlPullParser.START_TAG: {
                        switch (nodeName) {
                            case "key":
                                queryText.append(xmlPullParser.nextText()).append("\n\n");
                                break;
                            case "ps":
                                voiceText.append(xmlPullParser.nextText()).append("\n");
                                break;
                            case "pron":
                                voiceText.append(xmlPullParser.nextText()).append("\n\n");
                                break;
                            case "pos":
                                meanText.append(xmlPullParser.nextText()).append("  ");
                                break;
                            case "acceptation":
                                meanText.append(xmlPullParser.nextText()).append("\n");
                                break;
                            case "orig":
                                exampleText.append(xmlPullParser.nextText());
                                break;
                            case "trans":
                                exampleText.append(xmlPullParser.nextText());
                                break;
                        }
                        eventType = xmlPullParser.nextTag();
                        break;
                    }
                    default:
                        eventType = xmlPullParser.next();
                        break;
                }
            }

            TextView responseText = (TextView) findViewById(R.id.response);
            responseText.setText("查询文本:" + queryText + "发音信息:\n" + voiceText
                    + "基本释义:\n" + meanText + "相关例句:\n" + exampleText);

        } catch (Exception e) {
            e.printStackTrace();
            Log.d(TAG, "解析过程中出错!!!");
        }
    }
__椎名真白 2018-03-12
  • 打赏
  • 举报
回复
引用 4楼jklwan 的回复:
没有其他的属性还算简单了,另外如果是java7可以用switch代替,比if else效率高
对啊,debug的时候就发现它走的步骤特别多。java8就不能加switch了吗?或者我这段代码,是不是可以加一个case,如果是TAG_ENG,就跳往下一个标签。应该效率会提高一点。
__椎名真白 2018-03-11
  • 打赏
  • 举报
回复
圆满解决!!
代码:
//使用pull方式解析XML文件
public void parseJinshanEnglishToChineseXMLWithPull(String result) {

try {

XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser xmlPullParser = factory.newPullParser();
xmlPullParser.setInput(new StringReader(result));
int eventType = xmlPullParser.getEventType();

String queryText = ""; //查询文本
String voiceText = ""; //发音和发音地址信息
String meanText = ""; //基本释义信息
String exampleText = ""; //例句信息

while (eventType != XmlPullParser.END_DOCUMENT) {
String nodeName = xmlPullParser.getName();
switch (eventType) {
//开始解析
case XmlPullParser.START_TAG: {
if ("key".equals(nodeName)) {
queryText += xmlPullParser.nextText() + "\n\n";
} else if ("ps".equals(nodeName)) {
voiceText += xmlPullParser.nextText() +"\n";
} else if ("pron".equals(nodeName)) {
voiceText += xmlPullParser.nextText() +"\n\n";
} else if ("pos".equals(nodeName)) {
meanText += xmlPullParser.nextText() +" ";
} else if ("acceptation".equals(nodeName)) {
meanText += xmlPullParser.nextText() +"\n";
} else if ("orig".equals(nodeName)) {
exampleText += xmlPullParser.nextText();
}else if("trans".equals(nodeName)){
exampleText += xmlPullParser.nextText();
}
break;
}
default:
break;
}
eventType = xmlPullParser.next();
}

TextView responseText = (TextView) findViewById(R.id.response);

responseText.setText("查询文本:" + queryText + "发音信息:\n" + voiceText
+ "基本释义:\n" + meanText + "相关例句:\n" + exampleText);

} catch (Exception e) {
e.printStackTrace();
Log.d(TAG, "解析过程中出错!!!");
}

}

解决方法:放弃所有Bean,使用变量。以后存储到数据库也可以这么存储。
运行结果:


都没有大佬回复,弄了两天才搞好,脑阔疼。
来个大佬回复一下,我好结贴给分。
__椎名真白 2018-03-11
  • 打赏
  • 举报
回复
大佬们,现在所有问题都不是问题啦!~~不用再回答我上面的问题了。现在出现了一个很有意思的问题。还是解析过程中的。代码如下:
//使用pull方式解析XML文件
public void parseXMLWithPull(String result){

try {

XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser xmlPullParser = factory.newPullParser();
xmlPullParser.setInput(new StringReader(result));
int eventType = xmlPullParser.getEventType();

JinshanEnglishToChineseQueryBean queryBean = new JinshanEnglishToChineseQueryBean();
JinshanEnglishToChineseVoiceBean voiceBean = new JinshanEnglishToChineseVoiceBean();
// JinshanEnglishToChineseVoiceBean voiceBeanTemp = new JinshanEnglishToChineseVoiceBean();
JinshanEnglishToChineseMeanBean meanBean = new JinshanEnglishToChineseMeanBean();
JinshanEnglishToChineseExampleBean exampleBean = new JinshanEnglishToChineseExampleBean();

List<JinshanEnglishToChineseVoiceBean> voiceBeanList = new ArrayList<>();
List<JinshanEnglishToChineseMeanBean> meanBeanList = new ArrayList<>();
List<JinshanEnglishToChineseExampleBean> exampleBeanList = new ArrayList<>();

while(eventType != XmlPullParser.END_DOCUMENT){
String nodeName = xmlPullParser.getName();
switch(eventType){
//开始解析
case XmlPullParser.START_TAG:{
if("key".equals(nodeName)){
queryBean.setQuery(xmlPullParser.nextText());
}else if("ps".equals(nodeName)){
voiceBean.setVoice(xmlPullParser.nextText());
}else if("pron".equals(nodeName)){
voiceBean.setVoiceUrl(xmlPullParser.nextText());
voiceBeanList.add(voiceBean);

//新建一个临时对象
}

break;
}
default:
break;
}
eventType = xmlPullParser.next();
}

TextView responseText = (TextView) findViewById(R.id.response);
responseText.setText(queryBean.getQuery() + "\n" + voiceBeanList.get(0).getVoice() + "\n" + voiceBeanList.get(0).getVoiceUrl()
+ "\n" + voiceBeanList.get(1).getVoice() + "\n" + voiceBeanList.get(1).getVoiceUrl());

}catch(Exception e){
e.printStackTrace();
Log.d(TAG, "解析过程中出错!!!");
}

}

运行结果是:

很明显的第二个发音和地址把第一个覆盖了。两个url是一样的。出现这个问题的原因,debug之后发现,两次修改的VoiceBean指向的是一个地址。第二次修改会把前面的覆盖。接着voiceBeanList里装填好的第一个数据也跟着改变了。
这要怎么解决啊。。找到地方了。。不知道怎么解决。。新建一个临时对象来存储第一次修改的数据,然后voiceBeanList来add这个临时对象,也是不能解决问题。这要怎么办才好。。。怎么建立临时对象都不行。。有没有大佬遇见过同样的问题。。单纯的地址问题。求解决方案。。
__椎名真白 2018-03-10
  • 打赏
  • 举报
回复
我好像是发现了点什么。如果查询成功,发音可定存在,也用一个List就好了。否则一直都是给英式发音和网址赋值。哇!~ 新世界。静下来想想竟然想通了。明天试试。因该能成功了。

80,337

社区成员

发帖
与我相关
我的任务
社区描述
移动平台 Android
androidandroid-studioandroidx 技术论坛(原bbs)
社区管理员
  • Android
  • yechaoa
  • 失落夏天
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧