Xml简介
对Xml不太了解的同学可以看一下这篇Xml的简介:http://www.cnblogs.com/SkySoot/archive/2012/08/24/2654319.html
DOM解析Xml
Dom解析Xml的时候,会将Xml文件的所有内容以文件树的形式存储到内存中,然后用户通过使用DOM API遍历Xml树,检索需要的内容。
但是,因为它将文件树放在了内存中,如果文件较大的时候,对于安卓开发来说内存消耗太大,所以文件大时不推荐用DOM解析。
DOM解析的步骤如下:
1.利用DocumentBuilderFactory.newInstance()创建DocumentBuilderFactory实例
2.利用DocumentBuilderFactory创建DocumentBuilder
3.加载Document
4.获取文档根节点(Element)
5.用递归的方式读取各个子节点
/**
* 使用递归解析一个XML文档
*
*/
private void domParse() {
InputStream inputStream = null;
try {
inputStream = getResources().getAssets().open("myuser.xml");
} catch (IOException e) {
e.printStackTrace();
}
if(inputStream == null)
return;
StringBuffer stringBuffer = new StringBuffer();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
try {
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(inputStream);
Element rootElement = document.getDocumentElement();//users
stringBuffer.append(parseElement(rootElement));
textView.setText(stringBuffer.toString());
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private String parseElement(Element element) {
StringBuffer stringBuffer = new StringBuffer();
String tagName = element.getNodeName();
stringBuffer.append("<" + tagName);
// element元素的所有属性构成的NamedNodeMap对象,需要对其进行判断
NamedNodeMap attributeMap = element.getAttributes();
// 如果存在属性,则打印属性
if (null != attributeMap) {
for (int i = 0; i < attributeMap.getLength(); i++) {
// 获得该元素的每一个属性
Attr attr = (Attr) attributeMap.item(i);
// 属性名和属性值
String attrName = attr.getName();
String attrValue = attr.getValue();
// 注意属性值需要加上引号,所以需要\转义
stringBuffer.append(" " + attrName + "=\"" + attrValue + "\"");
}
}
// 关闭标签名
stringBuffer.append(">");
// 至此已经打印出了元素名和其属性
// 下面开始考虑它的子元素
NodeList children = element.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
// 获取每一个child
Node node = children.item(i);
// 获取节点类型
short nodeType = node.getNodeType();
if (nodeType == Node.ELEMENT_NODE) {
// 如果是元素类型,则递归输出
stringBuffer.append(parseElement((Element) node));
} else if (nodeType == Node.TEXT_NODE) {
// 如果是文本类型,则输出节点值,及文本内容
stringBuffer.append(node.getNodeValue());
} else if (nodeType == Node.COMMENT_NODE) {
// 如果是注释,则输出注释
stringBuffer.append("<!--");
Comment comment = (Comment) node;
// 注释内容
String data = comment.getData();
stringBuffer.append(data);
stringBuffer.append("-->");
}
}
// 所有内容处理完之后,输出,关闭根节点
stringBuffer.append("</" + tagName + ">");
return stringBuffer.toString();
}
SAX解析Xml
Sax是基于事件驱动,边加载边解析的。我们会在解析的时候收到相应事件的回调
Sax解析的步骤如下:
1.根据SAXParserFactory.newInstance()得到SAXParserFactory实例
2.根据SAXParserFactory得到SAXParser
3.继承DefaultHandler,实现它的回调函数(startDocument() , startElement() , characters() , endElement() , endDocument() )
4.调用saxParser的parse()方法开始解析
private void saxParse() {
InputStream inputStream = null;
try {
inputStream = getResources().getAssets().open("mylaunch.xml");
} catch (IOException e) {
e.printStackTrace();
}
if(inputStream == null)
return;
final StringBuffer stringBuffer = new StringBuffer();
SAXParserFactory factory = SAXParserFactory.newInstance();
try {
SAXParser saxParser = factory.newSAXParser();
DefaultHandler defaultHandler = new DefaultHandler(){
//开始解析文档,即开始解析XML根元素时调用该方法
@Override
public void startDocument() throws SAXException {
Log.d("zyr","startDocument");
super.startDocument();
}
//开始解析每个元素时都会调用该方法
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
Log.e("zyr","startElement " + qName);
super.startElement(uri, localName, qName, attributes);
stringBuffer.append("<" + qName);
if(attributes!=null){
for(int i=0;i<attributes.getLength();i++){
stringBuffer.append(" " + attributes.getQName(i) + "=" + attributes.getValue(i));
}
}
stringBuffer.append(">");
}
//解析到每个元素的内容时会调用此方法
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
Log.d("zyr","characters " + new String(ch,start,start+length));
super.characters(ch, start, length);
stringBuffer.append(new String(ch,start,start+length));
}
//每个元素结束的时候都会调用该方法
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
Log.e("zyr","endElement " + qName);
super.endElement(uri, localName, qName);
stringBuffer.append("</" + qName + ">");
}
//结束解析文档,即解析根元素结束标签时调用该方法
@Override
public void endDocument() throws SAXException {
Log.d("zyr","endDocument");
super.endDocument();
runOnUiThread(new Runnable() {
@Override
public void run() {
textView.setText(stringBuffer.toString());
}
});
}
};
saxParser.parse(inputStream,defaultHandler);
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
Pull解析Xml
Pull也是基于事件驱动的,它的使用步骤如下:
1.通过XmlPullParserFactory.newInstance()获取XmlPullParserFactory实例
2.通过XmlPullParserFactory获取XmlPullParser
3.通过xmlPullParser.setInput(inputStream,"UTF-8")设置输入流和编码
4.通过xmlPullParser.getEventType获得事件类型
5.通过xmlPullParser.next()循环,并且根据eventType进行相应的解析
private void pullParse() {
InputStream inputStream = null;
try {
inputStream = getResources().getAssets().open("myfriends.xml");
} catch (IOException e) {
e.printStackTrace();
}
if(inputStream == null)
return;
StringBuffer stringBuffer = new StringBuffer();
try {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser xmlPullParser = factory.newPullParser();
xmlPullParser.setInput(inputStream,"UTF-8");
int eventType = xmlPullParser.getEventType();
while (eventType!= XmlPullParser.END_DOCUMENT){
switch (eventType){
case XmlPullParser.START_DOCUMENT:
break;
case XmlPullParser.START_TAG:
stringBuffer.append("<" + xmlPullParser.getName());
for(int i=0;i<xmlPullParser.getAttributeCount();i++){
stringBuffer.append(" " + xmlPullParser.getAttributeName(i) + "=" + xmlPullParser.getAttributeValue(i));
}
stringBuffer.append(">");
break;
case XmlPullParser.TEXT:
stringBuffer.append(xmlPullParser.getText());
break;
case XmlPullParser.END_TAG:
stringBuffer.append("</" + xmlPullParser.getName() + ">");
break;
case XmlPullParser.END_DOCUMENT:
break;
}
eventType = xmlPullParser.next();
}
textView.append(stringBuffer.toString());
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
安卓写入Xml文件
安卓使用XmlSerializer创建Xml文件,具体步骤如下:
1.在manifest.xml中添加权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
2.在需要的路径创建一个File,并且获得File的outPutStream流
3.通过Xml.newSerializr()获得XmlSerializer
4.通过xmlSerializer.setOutput(outputStream,"UTF-8")设置流和编码
5.调用startDocument()方法写入xml开始的标志
6.调用setFeature方法设置属性
7.调用startTag方法写入开始标签,调用attribute方法写入属性
8.调用text方法写入内容
9.调用endTag方法结束标签
10.调用endDocument方法结束文档
11.调用xmlSerializer.flush()方法和fileOutputStream.close()方法
/**
* 使用XmlSerializer创建XML文件
*/
private void writeXml() {
//别忘记在Mainfest添加权限
//在SD卡创建名为poem.xml的文件
File xmlFile = new File(getApplicationContext().getFilesDir().getAbsolutePath()+"/poem.xml");
try {
xmlFile.createNewFile();
Log.d("zyr","path:" + xmlFile.getAbsolutePath());
FileOutputStream os = new FileOutputStream(xmlFile);
//创建XmlSerializer对象
XmlSerializer xmlSerializer = Xml.newSerializer();
xmlSerializer.setOutput(os,"UTF-8");
xmlSerializer.startDocument("UTF-8",Boolean.valueOf(true));
xmlSerializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output",true);
xmlSerializer.startTag(null,"poems");
xmlSerializer.startTag(null,"poem");
xmlSerializer.attribute(null,"id","1");
xmlSerializer.text("你是谁呀");
xmlSerializer.endTag(null,"poem");
xmlSerializer.startTag(null,"poem");
xmlSerializer.attribute(null,"id","2");
xmlSerializer.startTag(null,"author");
xmlSerializer.text("白居易");
xmlSerializer.endTag(null,"author");
xmlSerializer.startTag(null,"name");
xmlSerializer.text("待填写");
xmlSerializer.endTag(null,"name");
xmlSerializer.startTag(null,"content");
xmlSerializer.text("忘记了");
xmlSerializer.endTag(null,"content");
xmlSerializer.endTag(null,"poem");
xmlSerializer.endTag(null,"poems");
xmlSerializer.endDocument();
xmlSerializer.flush();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}