android中的网络解析xml,json,html框架

Posted 心之所善兮

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android中的网络解析xml,json,html框架相关的知识,希望对你有一定的参考价值。

android中网络请求回来数据之后,我们要对其解析。请求的返回的结果格式如果不是自定义协议;那么返回的数据通常是xml,json,html形式的数据了。

下面就是针对上面3种格式进行解析。

xml解析使用工具:在android中推荐使用pull解析,还有其他的dom,sax解析。

json解析使用工具:推荐使用Fastjson,由阿里提供。还有其他的如JackSon,Gson解析。

html解析使用工具:推荐使用Jsoup,还有其他的如HtmlParser;关于使用这个,网络上的爬虫就是这样子的。

1.Xml解析:

Pull解析;

//android推荐的解析方式
public class PULL {

	public static List<Person> pullXML() throws Exception {
		// 获取person文件的输入流
		InputStream is = PULL.class.getClassLoader().getResourceAsStream(
				"person.xml");
		// 用来存放解析的person对象
		List<Person> persons = null;
		// 一个标记
		boolean flag = false;
		Person person = null;

		// 实例化一个XmlPullParser对象
		XmlPullParser parser = Xml.newPullParser();

		// 设置输入流的编码
		parser.setInput(is, "UTF-8");

		// 设置第一个事件,从这个事件开始解析文档
		int eventCode = parser.getEventType();

		// 设定结束标记,如果是END_DOCUEMNT,解析就结束了
		while (eventCode != XmlPullParser.END_DOCUMENT) {
			switch (eventCode) {
			case XmlPullParser.START_DOCUMENT:
				// 开始解析的时候我们一般做一些初始化的操作
				persons = new ArrayList<Person>();
				break;
			case XmlPullParser.START_TAG:
				// 判断当前的元素是否是需要检索的元素
				if ("person".equals(parser.getName())) {
					flag = true;
					person = new Person();  
					//"person"节点的第一个属性值
					person.setId(Integer.valueOf(parser.getAttributeValue(0)));
				}
				if (flag) { // 为检索的元素赋值
					if ("name".equals(parser.getName())) {
						//"name"节点后的值
						person.setName(parser.nextText());
					} else if ("age".equals(parser.getName())) {
						person.setAge(Integer.valueOf(parser.nextText()));
					}
				}
				break;
			case XmlPullParser.END_TAG: // 结束标签,判断一个对象是否结束,结束后添加到集合中
				if ("person".equals(parser.getName()) && person != null) {
					flag = false;
					persons.add(person);
					person = null;
				}
				break;
			}
			// 这一步很重要,该方法返回一个事件码,也是触发下一个事件的方法
			eventCode = parser.next(); // 取下个标签
		}
		return persons;
	}
}

Dom解析;

public class DOM {

	public static List<Person> domXML() throws Throwable {
		// 获得xml文件的输入流
		InputStream is = MainActivity.class.getClassLoader()
				.getResourceAsStream("person.xml");
		List<Person> persons = new ArrayList<Person>();

		// 定义一个工厂API,程序可以从这个API里得到一个能够从XML文档中产生DOM对象的解析器- 翻译的不好
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document document = builder.parse(is);

		// 返回文档的根元素
		Element rootElement = (Element) document.getDocumentElement();

		// 获取一个Node集合
		NodeList nodes = rootElement.getElementsByTagName("person");

		// 遍历Node集合
		for (int i = 0; i < nodes.getLength(); i++) {
			Element personElement = (Element) nodes.item(i);
			Person person = new Person();
			person.setId(Integer.valueOf(personElement.getAttribute("id")));
			NodeList childNodes = personElement.getChildNodes();
			for (int j = 0; j < childNodes.getLength(); j++) {
				Node childNode = childNodes.item(j);
				// 判断子Note的类型为元素Note
				if (childNode.getNodeType() == Node.ELEMENT_NODE) {
					Element childElement = (Element) childNode;

					if ("name".equals(childElement.getNodeName())) {
						person.setName(childElement.getFirstChild()
								.getNodeValue());
					} else if ("age".equals(childElement.getNodeName())) {
						person.setAge(Integer.valueOf(childElement
								.getFirstChild().getNodeValue()));
					}
				}
			}
			persons.add(person);
		}
		return persons;
	}
}

Sax解析;

public class SAX extends DefaultHandler {
	
	public static List<Person> sax_XML() throws Exception {
		InputStream inputStream = MainActivity.class.getClassLoader()
				.getResourceAsStream("person.xml");
		if (inputStream != null) {
			Log.d("inputStream", inputStream + "");
		} else {
			Log.e("inputStream", inputStream + "为空");
		}
		SAX saXforHandler = new SAX();
		SAXParserFactory spf = SAXParserFactory.newInstance();
		SAXParser saxParser = spf.newSAXParser();
		saxParser.parse(inputStream, saXforHandler);
		List<Person> list = saXforHandler.getPersons();
		inputStream.close();
		return list;
	}

	/**
	 * This is log.d TAG
	 */
	private static final String TAG = "SAXTag";

	/**
	 * Store persons 存储人数组
	 */
	private List<Person> persons;

	/**
	 * a Person
	 */
	private Person person;

	/**
	 * recode the name of current tag
	 */
	private String tag;

	/**
	 * When startDocument,you can initial something in this method
	 * 当文档开始时,会调用这个方法
	 */
	@Override
	public void startDocument() throws SAXException {
		persons = new ArrayList<Person>();
		Log.d(TAG, "the sax is starting");

	}

	/**
	 * invoke the method after endDocument 文档结束时会调用这个方法
	 */
	@Override
	public void endDocument() throws SAXException {
		Log.d(TAG, "endDocument");
	}

	/**
	 * invoke when startElement 开始读取元素时候调用这个方法
	 */
	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		if ("person".equals(localName)) {
			for (int i = 0; i < attributes.getLength(); i++) {
				Log.d(TAG, "attributes.getLength" + attributes.getLength());
				Log.d(TAG, "attributesName: " + attributes.getLocalName(i)
						+ "_attributesValue" + attributes.getValue(i));
				person = new Person();
				person.setId(Integer.valueOf(attributes.getValue(i)));
			}
		}

		tag = localName;
		Log.i(TAG, "localName = " + localName);
	}

	/**
	 * read the element content 读取元素里面的内容。 比如说读到age,age的内容是21.这个方法就是来读21的
	 */
	@Override
	public void characters(char[] ch, int start, int length)
			throws SAXException {
		String data = new String(ch, start, length).trim();
		if (!"".equals(data)) {
			Log.i(TAG, "Content: " + data);
		}
		if ("name".equals(tag)) {
			person.setName(data);
		} else if ("age".equals(tag)) {
			person.setAge(Integer.valueOf(data));
		}
	}

	/**
	 * 一个元素结束时候调用 就是遇到反斜杠时候调用
	 */
	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		if ("person".equals(localName) && person != null) {
			persons.add(person);
			person = null;
		}
		tag = null;
	}

	private List<Person> getPersons() {
		return persons;
	}
}


2.Json解析:这里使用一种就可以了FastJson

/**
 * 
 * 
 * JSON.toJSONString;用于将实体类对象或实体集合转为Json格式字符
 * JSON.parseObject,JSON.parseArray用于将json格式字符转为实体对象或实体集合
 * 
 * 类似的实体与JSON格式之间的转换工具还有Gson,JackSon;
 * 
 * @author ZhangSheng
 * 
 */
public class FastJson {

	private static String TAG = "FastJson";

	/**
	 * 将实体对象或集合转为jsonsString
	 * 
	 * @param object
	 * @return
	 */
	public static String toJsonString(Object object) {
		return JSON.toJSONString(object);
	}

	/**
	 * 将jsonString转为实体对象
	 * 
	 * @param text
	 * @param clazz
	 * @return
	 */
	public static <T> T parseObject(String text, Class<T> clazz) {
		T object = JSON.parseObject(text, clazz);
		return object;
	}

	/**
	 * 将jsonString转为实体集合
	 * 
	 * @param text
	 * @param clazz
	 * @return
	 */
	public static <T> List<T> parseArray(String text, Class<T> clazz) {
		List<T> array = JSON.parseArray(text, clazz);
		return array;
	}

	/****************************** 测试 ***************************************/
	public static void test() {
		StudentInfo studentInfo1 = new StudentInfo("11", "11", 11);
		StudentInfo studentInfo2 = new StudentInfo("11", "11", 11);
		List<StudentInfo> students = new ArrayList<>();
		students.add(studentInfo1);
		students.add(studentInfo2);
		ClassInfo classInfo = new ClassInfo("1", "1", students);

		String students_Str = FastJson.toJsonString(students);
		Log.d(TAG, "students_Str=" + students_Str + "\n\n");

		String studentInfo_Str = FastJson.toJsonString(studentInfo1);
		String classInfo_Str = FastJson.toJsonString(classInfo);
		Log.d(TAG, "studentInfo_Str=" + studentInfo_Str + "\n classInfo_Str="
				+ classInfo_Str);

		StudentInfo parseObject = FastJson.parseObject(studentInfo_Str,
				StudentInfo.class);
		Log.d(TAG, "studentInfo=" + parseObject + "\n\n");
		
		List<StudentInfo> parseArray = FastJson.parseArray(students_Str, StudentInfo.class);
		Log.d(TAG, "StudentInfos=" + parseArray + "\n\n");
	}

	public static class StudentInfo {
		public String id;
		public String name;
		public int age;

		public StudentInfo() {
			super();
		}

		public StudentInfo(String id, String name, int age) {
			super();
			this.id = id;
			this.name = name;
			this.age = age;
		}

		@Override
		public String toString() {
			return "StudentInfo [id=" + id + ", name=" + name + ", age=" + age
					+ "]";
		}
	}

	public static class ClassInfo {
		public String id;
		public String name;
		public List<StudentInfo> students;

		public ClassInfo(String id, String name, List<StudentInfo> students) {
			super();
			this.id = id;
			this.name = name;
			this.students = students;
		}

		public ClassInfo() {
			super();
		}

		@Override
		public String toString() {
			return "ClassInfo [id=" + id + ", name=" + name + ", students="
					+ students + "]";
		}
	}

}


3.html解析:这里使用的是Jsoup。看起来有点复杂,没有详细的用过,不是很熟悉。

<p>Jsoup相关内容:涉及到html数据的输入,从html中抽取数据,修改html中的数据这三个部分。</p><h4>html数据的输入:</h4>
1.解析一个Html字符串:
	使用静态Jsoup.parse(String html) 方法或 Jsoup.parse(String html, String baseUri)
	如:
	String html = "<html><head><title>First parse</title></head>"
	+ "<body><p>Parsed HTML into a doc.</p></body></html>";
	Document doc = Jsoup.parse(html);
	另一个方法提供的参数 baseUri 是用来将相对 URL 转成绝对URL;
	一旦拥有了一个Document,你就可以使用Document中适当的方法或它父类 Element和Node中的方法来取得相关数据

2.解析一个body片段:
	假如你有一个HTML片断 (比如. 一个 div 包含一对 p 标签; 一个不完整的HTML文档) 想对它进行解析。
	使用Jsoup.parseBodyFragment(String html)
	String html = "<div><p>Lorem ipsum.</p>";
	Document doc = Jsoup.parseBodyFragment(html);
	Element body = doc.body();
	使用Document.body()方法能够取得文档body元素的所有子元素,与 doc.getElementsByTag("body")相同。
	
3.从一个网站Url上加载一个Document:
	使用Jsoup.connect(String url)
	如:
	Document doc = Jsoup.connect("http://example.com/").get();
	String title = doc.title();
	或者使用
	该方法,只支持http和https协议;
	Document doc = Jsoup.connect("http://example.com")
						.data("query", "Java")
						.userAgent("Mozilla")
						.cookie("auth", "token")
						.timeout(3000)
						.post();

4.加载本地硬盘上的html文件:
	使用Jsoup.parse(File in, String charsetName, String baseUri)
		baseUri 参数用于解决文件中URLs是相对路径的问题。如果不需要可以传入一个空的字符串。
	另外还有一个方法Jsoup.parse(File in, String charsetName)
		它使用文件的路径做为 baseUri, 这个方法适用于如果被解析文件位于网站的本地文件系统,且相关链接也指向该文件系统。
	如:
	File input = new File("/tmp/input.html");
	Document doc = Jsoup.parse(input, "UTF-8", "http://example.com/");
	
<h4>html数据的抽取:</h4>
1.使用dom方法来遍历一个document:
经过上面的数据的输入之后,我们可以获取到一个document对象。之后我们将对这个对象做数据抽取;
基本代码如下:这是是一个本地html文件抽取:
File input = new File("/tmp/input.html");
Document doc = Jsoup.parse(input, "UTF-8", "http://example.com/");

Element content = doc.getElementById("content");
Elements links = content.getElementsByTag("a");
for (Element link : links) {
  String linkHref = link.attr("href");
  String linkText = link.text();
}
下面是一些常见的方法:
查找元素
getElementById(String id)
getElementsByTag(String tag)
getElementsByClass(String className)
getElementsByAttribute(String key) (and related methods)
Element siblings: siblingElements(), firstElementSibling(), lastElementSibling(); nextElementSibling(), previousElementSibling()
Graph: parent(), children(), child(int index)

元素数据
attr(String key)获取属性attr(String key, String value)设置属性
attributes()获取所有属性
id(), className() and classNames()
text()获取文本内容text(String value) 设置文本内容
html()获取元素内HTMLhtml(String value)设置元素内的HTML内容
outerHtml()获取元素外HTML内容
data()获取数据内容(例如:script和style标签)
tag() and tagName()

操作HTML和文本
append(String html), prepend(String html)
appendText(String text), prependText(String text)
appendElement(String tagName), prependElement(String tagName)
html(String value)

2.使用选择器语法来查找元素:
	使用Element.select(String selector) 和 Elements.select(String selector) 
	如:
	File input = new File("/tmp/input.html");
	Document doc = Jsoup.parse(input, "UTF-8", "http://example.com/");

	Elements links = doc.select("a[href]"); //带有href属性的a元素
	Elements pngs = doc.select("img[src$=.png]");
	//扩展名为.png的图片

	Element masthead = doc.select("div.masthead").first();
	//class等于masthead的div标签

	Elements resultLinks = doc.select("h3.r > a"); //在h3元素之后的a元素

说明
jsoup elements对象支持类似于CSS (或jquery)的选择器语法,来实现非常强大和灵活的查找功能。.

这个select 方法在Document, Element,或Elements对象中都可以使用。且是上下文相关的,因此可实现指定元素的过滤,或者链式选择访问。

Select方法将返回一个Elements集合,并提供一组方法来抽取和处理结果。

Selector选择器概述
tagname: 通过标签查找元素,比如:a
ns|tag: 通过标签在命名空间查找元素,比如:可以用 fb|name 语法来查找 <fb:name> 元素
#id: 通过ID查找元素,比如:#logo
.class: 通过class名称查找元素,比如:.masthead
[attribute]: 利用属性查找元素,比如:[href]
[^attr]: 利用属性名前缀来查找元素,比如:可以用[^data-] 来查找带有HTML5 Dataset属性的元素
[attr=value]: 利用属性值来查找元素,比如:[width=500]
[attr^=value], [attr$=value], [attr*=value]: 利用匹配属性值开头、结尾或包含属性值来查找元素,比如:[href*=/path/]
[attr~=regex]: 利用属性值匹配正则表达式来查找元素,比如: img[src~=(?i)\.(png|jpe?g)]
*: 这个符号将匹配所有元素
Selector选择器组合使用
el#id: 元素+ID,比如: div#logo
el.class: 元素+class,比如: div.masthead
el[attr]: 元素+class,比如: a[href]
任意组合,比如:a[href].highlight
ancestor child: 查找某个元素下子元素,比如:可以用.body p 查找在"body"元素下的所有 p元素
parent > child: 查找某个父元素下的直接子元素,比如:可以用div.content > p 查找 p 元素,也可以用body > * 查找body标签下所有直接子元素
siblingA + siblingB: 查找在A元素之前第一个同级元素B,比如:div.head + div
siblingA ~ siblingX: 查找A元素之前的同级X元素,比如:h1 ~ p
el, el, el:多个选择器组合,查找匹配任一选择器的唯一元素,例如:div.masthead, div.logo
伪选择器selectors
:lt(n): 查找哪些元素的同级索引值(它的位置在DOM树中是相对于它的父节点)小于n,比如:td:lt(3) 表示小于三列的元素
:gt(n):查找哪些元素的同级索引值大于n,比如: div p:gt(2)表示哪些div中有包含2个以上的p元素
:eq(n): 查找哪些元素的同级索引值与n相等,比如:form input:eq(1)表示包含一个input标签的Form元素
:has(seletor): 查找匹配选择器包含元素的元素,比如:div:has(p)表示哪些div包含了p元素
:not(selector): 查找与选择器不匹配的元素,比如: div:not(.logo) 表示不包含 class=logo 元素的所有 div 列表
:contains(text): 查找包含给定文本的元素,搜索不区分大不写,比如: p:contains(jsoup)
:containsOwn(text): 查找直接包含给定文本的元素
:matches(regex): 查找哪些元素的文本匹配指定的正则表达式,比如:div:matches((?i)login)
:matchesOwn(regex): 查找自身包含文本匹配指定正则表达式的元素
注意:上述伪选择器索引是从0开始的,也就是说第一个元素索引值为0,第二个元素index为1等
可以查看Selector API参考来了解更详细的内容
	
3.抽取元素属性,文本,html
	要取得一个属性的值,可以使用Node.attr(String key) 方法
	对于一个元素中的文本,可以使用Element.text()方法
	对于要取得元素或属性中的HTML内容,可以使用Element.html(), 或 Node.outerHtml()方法
	如:
	String html = "<p>An <a href='http://example.com/'><b>example</b></a> link.</p>";
	Document doc = Jsoup.parse(html);//解析HTML字符串返回一个Document实现
	Element link = doc.select("a").first();//查找第一个a元素

	String text = doc.body().text(); // "An example link"//取得字符串中的文本
	linkHref = link.attr("href"); // "http://example.com/"//取得链接地址
	String linkText = link.text(); // "example""//取得链接地址中的文本

	String linkOuterH = link.outerHtml(); 
    // "<a href="http://example.com"><b>example</b></a>"
	String linkInnerH = link.html(); // "<b>example</b>"//取得链接内的html内容
	说明
上述方法是元素数据访问的核心办法。此外还其它一些方法可以使用:

Element.id()
Element.tagName()
Element.className() and Element.hasClass(String className)
这些访问器方法都有相应的setter方法来更改数据.
	
4.处理URLs:
	在你解析文档时确保有指定base URI,然后使用 abs: 属性前缀来取得包含base URI的绝对路径
	如:
	Document doc = Jsoup.connect("http://www.open-open.com").get();

	Element link = doc.select("a").first();
	String relHref = link.attr("href"); // == "/"
	String absHref = link.attr("abs:href"); // "http://www.open-open.com/"
	
<h4>Html数据的修改:</h4>
1.设置属性的值:
		使用 Element.attr(String key, String value), 和 Elements.attr(String key, String value).
		Element.addClass(String className) 和 Element.removeClass(String className) 方法。
	如:
	doc.select("div.masthead").attr("title", "jsoup").addClass("round-box");

2.设置一个元素的Html内容:
		Element.html(String html) 这个方法将先清除元素中的HTML内容,然后用传入的HTML代替。
		Element.prepend(String first) 和 Element.append(String last) 方法用于在分别在元素内部HTML的前面和后面添加HTML内容
		Element.wrap(String around) 对元素包裹一个外部HTML内容。
	如:
	Element div = doc.select("div").first(); // <div></div>
	div.html("<p>lorem ipsum</p>"); // <div><p>lorem ipsum</p></div>
	div.prepend("<p>First</p>");//在div前添加html内容
	div.append("<p>Last</p>");//在div之后添加html内容
	// 添完后的结果: <div><p>First</p><p>lorem ipsum</p><p>Last</p></div>

	Element span = doc.select("span").first(); // <span>One</span>
	span.wrap("<li><a href='http://example.com/'></a></li>");
	// 添完后的结果: <li><a href="http://example.com"><span>One</span></a></li>
	
3.设置一个元素的文本内容:
		Element.text(String text) 将清除一个元素中的内部HTML内容,然后提供的文本进行代替
		Element.prepend(String first) 和 Element.append(String last) 将分别在元素的内部html前后添加文本节点。
		对于传入的文本如果含有像 <, > 等这样的字符,将以文本处理,而非HTML。
	如:
	Element div = doc.select("div").first(); // <div></div>
	div.text("five > four"); // <div>five > four</div>
	div.prepend("First ");
	div.append(" Last");
	// now: <div>First five > four Last</div>
	
<h4>最后是一个获取所有链接的例子:</h4>
/**
 * Example program to list links from a URL.
 */
public class ListLinks {
    public static void main(String[] args) throws IOException {
        Validate.isTrue(args.length == 1, "usage: supply url to fetch");
        String url = args[0];
        print("Fetching %s...", url);

        Document doc = Jsoup.connect(url).get();
        Elements links = doc.select("a[href]");
        Elements media = doc.select("[src]");
        Elements imports = doc.select("link[href]");

        print("\nMedia: (%d)", media.size());
        for (Element src : media) {
            if (src.tagName().equals("img"))
                print(" * %s: <%s> %sx%s (%s)",
                        src.tagName(), src.attr("abs:src"), src.attr("width"), src.attr("height"),
                        trim(src.attr("alt"), 20));
            else
                print(" * %s: <%s>", src.tagName(), src.attr("abs:src"));
        }

        print("\nImports: (%d)", imports.size());
        for (Element link : imports) {
            print(" * %s <%s> (%s)", link.tagName(),link.attr("abs:href"), link.attr("rel"));
        }

        print("\nLinks: (%d)", links.size());
        for (Element link : links) {
            print(" * a: <%s>  (%s)", link.attr("abs:href"), trim(link.text(), 35));
        }
    }

    private static void print(String msg, Object... args) {
        System.out.println(String.format(msg, args));
    }

    private static String trim(String s, int width) {
        if (s.length() > width)
            return s.substring(0, width-1) + ".";
        else
            return s;
    }
}
	
	
	
	
	
	
	
	
	
	








以上是关于android中的网络解析xml,json,html框架的主要内容,如果未能解决你的问题,请参考以下文章

Android解析服务器响应数据

Android 解析JSON格式数据

iOS网络编程开发—JSON解析与XML解析

Android之解析XML格式数据

Android - 将 XML 解析为 JSON

android 访问web端与解析json,模拟用户登录