【问题标题】:How to parse the xml when a xml document have multi hierarchy parent ?当 xml 文档具有多层次父级时如何解析 xml?
【发布时间】:2014-03-18 04:01:08
【问题描述】:

我正在尝试从响应中解析 xml 流以填充我的 android 应用程序中的某些字段。如果响应中包含一个关键节点项和多个子项,我可以解析响应。

XML 是

<?xml version="1.0" encoding="UTF-8"?>
<menu>
<item>
    <id>1</id>    
    <name>Margherita</name>
    <cost>155</cost>
    <description>Single cheese topping</description>
</item> 
<item>
    <id>2</id>    
    <name>Double Cheese Margherita</name>
    <cost>225</cost>
    <description>Loaded with Extra Cheese</description>
</item> 
<item>
    <id>3</id>    
    <name>Fresh Veggie</name>
    <cost>110</cost>
    <description>Oninon and Crisp capsicum</description>
</item> 
<item>
    <id>4</id>    
    <name>Peppy Paneer</name>
    <cost>155</cost>
    <description>Paneer, Crisp capsicum and Red pepper</description>
</item> 
<item>
    <id>5</id>    
    <name>Mexican Green Wave</name>
    <cost>445</cost>
    <description>Onion, Crip capsicum, Tomato with mexican herb</description>
</item> 
</menu>

我的 xml 解析器在下面

import java.io.IOException;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import android.util.Log;

public class XMLParser {

// constructor
public XMLParser() {

}

/**
 * Getting XML from URL making HTTP request
 * @param url string
 * */
public String getXmlFromUrl(String url) {
    String xml = null;

    try {
        // defaultHttpClient
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpPost httpPost = new HttpPost(url);

        HttpResponse httpResponse = httpClient.execute(httpPost);
        HttpEntity httpEntity = httpResponse.getEntity();
        xml = EntityUtils.toString(httpEntity);

    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (ClientProtocolException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    // return XML
    return xml;
}

/**
 * Getting XML DOM element
 * @param XML string
 * */
public Document getDomElement(String xml){
    Document doc = null;
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    try {

        DocumentBuilder db = dbf.newDocumentBuilder();

        InputSource is = new InputSource();
            is.setCharacterStream(new StringReader(xml));
            doc = db.parse(is); 

        } catch (ParserConfigurationException e) {
            Log.e("Error: ", e.getMessage());
            return null;
        } catch (SAXException e) {
            Log.e("Error: ", e.getMessage());
            return null;
        } catch (IOException e) {
            Log.e("Error: ", e.getMessage());
            return null;
        }

        return doc;
}

/** Getting node value
  * @param elem element
  */
 public final String getElementValue( Node elem ) {
     Node child;
     if( elem != null){
         if (elem.hasChildNodes()){
             for( child = elem.getFirstChild(); child != null; child = child.getNextSibling() ){
                 if( child.getNodeType() == Node.TEXT_NODE  ){
                     return child.getNodeValue();
                 }
             }
         }
     }
     return "";
 }

 /**
  * Getting node value
  * @param Element node
  * @param key string
  * */
 public String getValue(Element item, String str) {     
        NodeList n = item.getElementsByTagName(str);        
        return this.getElementValue(n.item(0));
    }

我的解析代码是

static final String URL = "http://api.androidhive.info/pizza/?format=xml";
static final String KEY_ITEM = "item"; // parent node
static final String KEY_NAME = "name";
static final String KEY_COST = "cost";
static final String KEY_DESC = "description";

XMLParser parser = new XMLParser();
String xml = parser.getXmlFromUrl(URL); // getting XML
Document doc = parser.getDomElement(xml); // getting DOM element

NodeList nl = doc.getElementsByTagName(KEY_ITEM);
for (int i = 0; i < nl.getLength(); i++) {
String name = parser.getValue(e, KEY_NAME); // name child value
String cost = parser.getValue(e, KEY_COST); // cost child value
String description = parser.getValue(e, KEY_DESC); // description child value
}

例如,当 xml 变为多级时,我的问题就开始了

<?xml version="1.0" encoding="UTF-8"?>
<menu>
<item>
<id>1</id>    
<name>Margherita</name>
<originalcost>
<cost>
<ori_cost>$30</ori_cost><tax>$.2</tax>
</cost>
</originalcost>
<description>Single cheese topping</description>
</item> 
</menu>

我该如何解析上面说的例子?

【问题讨论】:

  • 为什么不用xml pullparser

标签: java android xml parsing


【解决方案1】:

引用文档

我们推荐 XmlPullParser,这是一种高效且可维护的方式 在 Android 上解析 XML。

http://developer.android.com/training/basics/network-ops/xml.html

您可以使用 xml 拉解析器

public class XMLPullParserHandler {

    private String text;

    public XMLPullParserHandler() {

    }



    public Void parse(InputStream is) {
        XmlPullParserFactory factory = null;
        XmlPullParser parser = null;
        try {
            factory = XmlPullParserFactory.newInstance();
            factory.setNamespaceAware(true);
            parser = factory.newPullParser();

            parser.setInput(is, null);

            int eventType = parser.getEventType();
            while (eventType != XmlPullParser.END_DOCUMENT) {
                String tagname = parser.getName();
                switch (eventType) {
                case XmlPullParser.START_TAG:
                    if (tagname.equalsIgnoreCase("menu")) {

                    }

                    break;

                case XmlPullParser.TEXT:
                    text = parser.getText();
                    break;

                case XmlPullParser.END_TAG:
                    if (tagname.equalsIgnoreCase("menu")) {
                        // add employee object to list

                    } else if (tagname.equalsIgnoreCase("item")) {

                    } else if (tagname.equalsIgnoreCase("id")) {

                        Log.i("id is",text);
                    }
                    else if (tagname.equalsIgnoreCase("name")) {

                        Log.i("name is",text);
                    }
                   else if (tagname.equalsIgnoreCase("originalcost")) {


                    }
                   else if (tagname.equalsIgnoreCase("ori_cost")) {

                       Log.i("original cost is",text);
                   }
                  else if (tagname.equalsIgnoreCase("tax")) {

                       Log.i("tax is",text);
                   }
                  else if (tagname.equalsIgnoreCase("description")) {

                   Log.i("description is",text);
                  }
                    break;

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

        } catch (XmlPullParserException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }
}

日志

03-18 01:22:39.980: I/id is(954): 1
03-18 01:22:39.980: I/name is(954): Margherita
03-18 01:22:39.990: I/original cost is(954): $30
03-18 01:22:39.990: I/tax is(954): $.2
03-18 01:22:39.990: I/description is(954): Single cheese topping

编辑:

获取xml fom url并转换为输入流

HttpClient httpclient = new DefaultHttpClient();
httpclient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
HttpGet request = new HttpGet("url");  
HttpResponse response = httpclient.execute(request);
HttpEntity resEntity = response.getEntity();
String  _response=EntityUtils.toString(resEntity); 
InputStream is = new ByteArrayInputStream(_response.getBytes()); 

编辑 2:

public class XMLPullParserHandler {

    private String text;

    public XMLPullParserHandler() {

    }



    public Void parse(InputStream is) {
        XmlPullParserFactory factory = null;
        XmlPullParser parser = null;
        try {
            factory = XmlPullParserFactory.newInstance();
            factory.setNamespaceAware(true);
            parser = factory.newPullParser();

            parser.setInput(is, null);

            int eventType = parser.getEventType();
            while (eventType != XmlPullParser.END_DOCUMENT) {
                String tagname = parser.getName();
                switch (eventType) {
                case XmlPullParser.START_TAG:
                    if (tagname.equalsIgnoreCase("xml")) {

                    }

                    break;

                case XmlPullParser.TEXT:
                    text = parser.getText();
                    break;

                case XmlPullParser.END_TAG:
                    if (tagname.equalsIgnoreCase("xml")) {
                        // add employee object to list

                    } else if (tagname.equalsIgnoreCase("leaders")) {
                         // no value

                    } 
                    else if (tagname.equalsIgnoreCase("leader")) {
                       // no vlaue

                    } else if (tagname.equalsIgnoreCase("image")) {

                        Log.i("image is",text);
                    }
                    else if (tagname.equalsIgnoreCase("name")) {

                        Log.i("name is",text);
                    }
                   else if (tagname.equalsIgnoreCase("SP DASH")) {


                    }
                   else if (tagname.equalsIgnoreCase("state")) {

                       Log.i("state is",text);
                   }
                  else if (tagname.equalsIgnoreCase("constituency")) {

                       Log.i("constituency is",text);
                   }
                  else if (tagname.equalsIgnoreCase("menu")) {

                   Log.i("menu is",text);
                  }
                  else if (tagname.equalsIgnoreCase("description")) {

                      // no vlaue
                     }
                  else if (tagname.equalsIgnoreCase("p")) {
                      Log.i("p is",text);

                  }
                  else if (tagname.equalsIgnoreCase("imagelink")) {
                      Log.i("imagelink is",text);

                  }
                    break;

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

        } catch (XmlPullParserException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }
}

日志

03-18 06:38:28.729: I/image is(1345): hdwallpaperdownloads.com/… 
03-18 06:38:28.729: I/image is(1345):             
03-18 06:38:28.729: I/name is(1345): SP DASH 
03-18 06:38:28.729: I/name is(1345):             
03-18 06:38:28.729: I/state is(1345): Delhi
03-18 06:38:28.729: I/state is(1345):             
03-18 06:38:28.729: I/constituency is(1345): Delhi
03-18 06:38:28.729: I/constituency is(1345):             
03-18 06:38:28.739: I/menu is(1345): profile,gallery,video
03-18 06:38:28.739: I/menu is(1345):             
03-18 06:38:28.739: I/p is(1345): lflsahflkfhalfkhlskfhalh 
03-18 06:38:28.739: I/p is(1345):                 
03-18 06:38:28.739: I/imagelink is(1345): hdwallpaperdownloads.com/… 
03-18 06:38:28.739: I/imagelink is(1345):                 
03-18 06:38:28.739: I/imagelink is(1345): hdwallpaperdownloads.com/… 
03-18 06:38:28.739: I/imagelink is(1345):                 
03-18 06:38:28.739: I/imagelink is(1345): hdwallpaperdownloads.com/… 
03-18 06:38:28.739: I/imagelink is(1345):                 
03-18 06:38:28.739: I/imagelink is(1345): hdwallpaperdownloads.com/… 
03-18 06:38:28.739: I/imagelink is(1345):                 
03-18 06:38:28.739: I/imagelink is(1345): hdwallpaperdownloads.com/… 
03-18 06:38:28.739: I/imagelink is(1345):      

【讨论】:

  • 我必须在哪里发送 URL 才能获得响应?@Raghunandan 因为你知道我收到了一个字符串作为响应,所以我可以在 setInput 中设置字符串而不是在 inputstream 中吗?
  • @Saty 您需要从 url 中提取 xml 并将其作为输入流传递
  • 好吧@Raghunandan,在我下载了 xml 之后,我可以这样写吗? InputStream in = IOUtils.toInputStream(string, "UTF-8");
  • 好的@Raghunandan 我需要你的最后帮助....我怎么知道要解析多少个元素(在我的例子中是“item”)?
  • 我没有得到你所说的内部节点值,而且如果有很多项目,那么它只会解析一个。我如何让它解析多个?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-25
  • 1970-01-01
  • 1970-01-01
  • 2020-07-10
  • 1970-01-01
  • 2018-08-25
相关资源
最近更新 更多