零、前言
Xml是一种应用广泛的标记语言,我们常见的html便是它的子集。形如:<XXX>xxx</XXX>组成的闭合标签
安卓的res目录下的xml想必大家都是否熟悉,它们最终都是在代码中被读取并解析发挥效果的
安卓的SharedPreferences是以Xml的形式存储数据的,就连AndroidManifest注意一看也是Xml
可以说xml涉及到了安卓的很多方面,我们并不陌生,Xml最大的好处就是解耦,容易复用和更换
pull解析.png
XML常见的三种解析方式:
解析方式 |
加载驱动方式 |
可修改? |
自定义结束? |
效率 |
备注 |
Pull解析 |
事件驱动 |
否 |
是 |
高 |
安卓专有 |
Sax解析 |
事件驱动 |
否 |
否 |
高 |
无 |
Dom解析 |
直接全部加载 |
是 |
否 |
低 |
解析时构建dom树 |
准备的待解析xml:
<?xml version="1.0" encoding="UTF-8"?>
<weapons>
<weapon material="玉" type="剑">
<name>问天剑</name>
<atk>2000</atk>
<user>语熙华</user>
</weapon>
<weapon material="铁" type="刀">
<name>皇刀</name>
<atk>3000</atk>
<user>九方玄玉</user>
</weapon>
</weapons>
一、Pull解析概述
Pull是安卓内置的,基于事件触发的解析器
Pull解析器小巧轻便,解析速度快,简单易用
主动从解析器中获取事件,可以在满足了需要的条件后不再获取事件,结束解析
1、Pull解析Xml:
private ArrayList<WeaponXml> parseXmlWithPull() {
InputStream is = null;
try {
//XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
//XmlPullParser pullParser = factory.newPullParser();
//获得Xml解析器--等价上两句
XmlPullParser pullParser = Xml.newPullParser();
//得到一个含有xml的is输入流
is = getAssets().open("weapon.xml");
//设置输入流
pullParser.setInput(is, "utf-8");
//触发第一个事件:eventType=0 即:START_DOCUMENT
int eventType = pullParser.getEventType();
//没有读到文档结束之前都在while里走
while (eventType != XmlPullParser.END_DOCUMENT) {
switch (eventType) {//根据事件类型执行
case XmlPullParser.START_DOCUMENT://文档开始
//新建对象的集合
mWeapons = new ArrayList<>();
break;
case XmlPullParser.START_TAG://读到第一个标签时再进行switch选择
switch (pullParser.getName()) {//拿到标签名称
case "weapon"://如果标签是weapon
//新建一个 Weapon对象用来记录信息
mWeapon = new WeaponXml();
//获取第一个属性值
String material = pullParser.getAttributeValue(0);
//获取第二个属性值
String type = pullParser.getAttributeValue(1);
//对象装载得到的属性
mWeapon.setType(type);
mWeapon.setMaterial(material);
break;
case "name":
//对于没有属性的标签,可以用nextText获取标签内部的文字
String name = pullParser.nextText();
mWeapon.setName(name);
break;
case "atk":
Short atk = new Short(pullParser.nextText());
mWeapon.setAtk(atk);
break;
case "user":
String user = pullParser.nextText();
mWeapon.setUser(user);
break;
}
break;
case XmlPullParser.END_TAG://当事件类型是终止标签时:即</XXX>
if ("weapon".equals(pullParser.getName())) {
mWeapons.add(mWeapon);//将生成对象加入集合,一个
}
break;
}
eventType = pullParser.next();//解析下一元素,更新event
}
} catch (Exception e) {
e.printStackTrace();
}finally {
if (is != null) {
try {
is.close();//关流
} catch (IOException e) {
e.printStackTrace();
}
}
}
return mWeapons;
}
2、Pull写入Xml:
/**
* 备份Xml--当然也可以备份任意的实体类作为Xml,比如短信,联系人
*/
private void backUpXml() {
ArrayList<WeaponXml> weapons = parseXmlWithPull();
XmlSerializer serializer = Xml.newSerializer();
FileOutputStream fos = null;
try {
String path = Environment.getExternalStorageDirectory().getAbsolutePath();
fos = new FileOutputStream(path + File.separator + "weapon.xml");
serializer.setOutput(fos, "utf-8");
//文档开始
serializer.startDocument("utf-8", true);
serializer.startTag("", "weapons");
for (WeaponXml weapon : weapons) {
//新建标签: <weapon>
serializer.startTag(null, "weapon");
//设置属性: material="玉" type="剑"
serializer.attribute("","material", weapon.getMaterial());
serializer.attribute("","type", weapon.getType());
//嵌套子标签:<name>问天剑</name>
serializer.startTag(null, "name");
serializer.text(weapon.getName().trim());
serializer.endTag(null, "name");
serializer.startTag(null, "atk");
serializer.text(weapon.getAtk() + "");
serializer.endTag(null, "atk");
serializer.startTag(null, "user");
serializer.text(weapon.getUser().trim());
serializer.endTag(null, "user");
//终止标签: </weapon>
serializer.endTag(null, "weapon");
}
serializer.endTag("", "weapons");//标签结束
serializer.endDocument();//文档结束
} catch (Exception e) {
e.printStackTrace();
}finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
二、Sax解析概述:(Simple API for XML)
Sax解析方式会逐行地去扫描XML文档,当遇到标签时会触发解析处理器,采用事件处理的方式解析XML
优点:在读取文档的同时即可对XML进行处理,不必等到文档加载结束,相对快捷,所以可以解析超大XML
缺点:只能用来读取XML中数据,无法进行增删改。
1、Sax解析Xml
/**
*
* @return
*/
private ArrayList<WeaponXml> parseXmlWithSax() {
InputStream is = null;
mWeapons = new ArrayList<>();
try {
SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
is = getAssets().open("weapon.xml");
saxParser.parse(is, new DefaultHandler() {
/**
* 开始标签时
* @param uri 命名空间
* @param localName 标签名
* @param qName 全名(带命名空间的标签的名字)
* @param attributes 属性
* @throws SAXException
*/
@Override
public void startElement(String uri, String localName,
String qName, Attributes attributes) throws SAXException {
//"属性名:" + attributes.getLocalName(i)
//"属性值:" + attributes.getValue(i));
if ("weapon".equals(localName)) {
mWeapon = new WeaponXml();
mWeapon.setMaterial(attributes.getValue(0));
mWeapon.setType(attributes.getValue(1));
}
mPerTag = localName;
}
/**解析标签的内容的时候调用
*
* @param ch 当前文本节点的字节数组
* @param start 字节开始的位置 默认 0 全部读取
* @param length 长度
* @throws SAXException
*/
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
String chars = new String(ch, start, length).trim();
if ("name".equals(mPerTag)) {
mWeapon.setName(chars);
} else if ("atk".equals(mPerTag)) {
mWeapon.setAtk(Integer.parseInt(chars));
} else if ("user".equals(mPerTag)) {
mWeapon.setUser(chars);
}
}
/**
* 标签解析结束调用
* @param uri
* @param localName
* @param qName
* @throws SAXException
*/
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if ("weapon".equals(localName)) {
mWeapons.add(mWeapon);
mWeapon = null;
}
mPerTag = null;
}
});
} catch (Exception e) {
e.printStackTrace();
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return mWeapons;
}
2、Sax存储Xml
/**
* sax创建Xml文件
*/
private void saxCreateXml() {
ArrayList<WeaponXml> weaponXmls = parseXmlWithSax();
//1、创建一个SAXTransformerFactory的对象
SAXTransformerFactory saxTF = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
FileOutputStream fos = null;
try {
//创建一个Transformer对象
TransformerHandler handler = saxTF.newTransformerHandler();
Transformer transformer = handler.getTransformer();
transformer.setOutputProperty(OutputKeys.ENCODING, "utf-8");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
String path = Environment.getExternalStorageDirectory().getAbsolutePath();
fos = new FileOutputStream(path + File.separator + "weaponSax.xml");
StreamResult result = new StreamResult(fos);
handler.setResult(result);
//开始
handler.startDocument();
AttributesImpl atts = new AttributesImpl();
handler.startElement("", "", "weapons", atts);
for (WeaponXml weaponXml : weaponXmls) {
atts.clear();
atts.addAttribute("", "", "material", "", weaponXml.getMaterial());
atts.addAttribute("", "", "type", "", weaponXml.getType());
handler.startElement("", "", "weapon", atts);
atts.clear();
handler.startElement("", "", "name", atts);
handler.characters(weaponXml.getName().toCharArray(), 0, weaponXml.getName().length());
handler.endElement("", "", "name");
atts.clear();
handler.startElement("", "", "atk", atts);
String atk = String.valueOf(weaponXml.getAtk());
handler.characters(atk.toCharArray(), 0, atk.length());
handler.endElement("", "", "atk");
atts.clear();
handler.startElement("", "", "user", atts);
handler.characters(weaponXml.getUser().toCharArray(), 0, weaponXml.getUser().length());
handler.endElement("", "", "user");
handler.endElement("", "", "weapon");
}
handler.endElement("", "", "weapons");
//关闭document
handler.endDocument();
} catch (Exception e) {
e.printStackTrace();
}finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
三、DOM解析概述:
DOM将整个XML文件加载到内存中,并构建出节点树;
应用程序可以通过遍历节点树的方式来解析XML文件中的各个节点、属性等信息;
优点:对XML节点的添加修改等,而且解析也很方便
缺点比较耗费内存,解析速度也不快
1、dom解析Xml
/**
* dom解析Xml
* @return
*/
private ArrayList<WeaponXml> parseXmlWithDom() {
mWeapons = new ArrayList<>();
InputStream is = null;
try {
is = getAssets().open("weapon.xml");
//获取document对象
Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(is);
//获取根元素
Element root = dom.getDocumentElement();
//获取weapon节点
NodeList weaponNode = root.getElementsByTagName("weapon");
for (int i = 0; i < weaponNode.getLength(); i++) {
mWeapon = new WeaponXml();
//获取person下第i个元素
Element weaponEl = (Element) weaponNode.item(i);
String material = weaponEl.getAttribute("material");//得到第i个属性值
String type = weaponEl.getAttribute("type");//得到第i个属性值
mWeapon.setMaterial(material);
mWeapon.setType(type);
NodeList childNodes = weaponEl.getChildNodes();//获得获取weapon下子元素
for (int j = 0; j < childNodes.getLength(); j++) {
if (childNodes.item(j).getNodeType() == Node.ELEMENT_NODE) {
String nodeName = childNodes.item(j).getNodeName();
if ("name".equals(nodeName)) {
String name = childNodes.item(j).getFirstChild().getNodeValue();
mWeapon.setName(name);
} else if ("atk".equals(nodeName)) {
String atk = childNodes.item(j).getFirstChild().getNodeValue();
mWeapon.setAtk(Integer.parseInt(atk));
} else if ("user".equals(nodeName)) {
String user = childNodes.item(j).getFirstChild().getNodeValue();
mWeapon.setUser(user);
}
}
}
mWeapons.add(mWeapon);
}
} catch (Exception e) {
e.printStackTrace();
}
return mWeapons;
}
2、dom存储Xml
/**
* sax创建Xml文件
*/
private void domCreateXml() {
try {
ArrayList<WeaponXml> weaponXmls = parseXmlWithDom();
//创建Dom解析器
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
//新建空白文档
Document doc = builder.newDocument();
//建立根元素employees
Element root = doc.createElement("weapons");
//将根节点添加进入文档
doc.appendChild(root);
for (WeaponXml weaponXml : weaponXmls) {
Element weapon = doc.createElement("weapon");
weapon.setAttribute("material", weaponXml.getMaterial());
weapon.setAttribute("type", weaponXml.getType());
root.appendChild(weapon);
Element name = doc.createElement("name");
name.appendChild(doc.createTextNode(weaponXml.getName()));
weapon.appendChild(name);
Element atk = doc.createElement("atk");
atk.appendChild(doc.createTextNode(weaponXml.getAtk()+""));
weapon.appendChild(atk);
Element user = doc.createElement("user");
user.appendChild(doc.createTextNode(weaponXml.getUser()));
weapon.appendChild(user);
}
//为了得到xslt引擎创建对象
TransformerFactory tff = TransformerFactory.newInstance();
//创建xslt引擎对象输出xml文档
Transformer tf = tff.newTransformer();
//获取属性对象
Properties pro = tf.getOutputProperties();
//设置编码格式和输出格式
pro.setProperty(OutputKeys.ENCODING, "utf-8");
pro.setProperty(OutputKeys.METHOD, "xml");
tf.setOutputProperties(pro);
//创建资源对象
DOMSource source = new DOMSource(doc);
String path = Environment.getExternalStorageDirectory().getAbsolutePath()
+File.separator+"WeaponDom.xml";
//获得输出对象
StreamResult result = new StreamResult(new File(path));
//执行dom文档到xml文件转换
tf.transform(source, result);
} catch (Exception e) {
e.printStackTrace();
}
后记:捷文规范
1.本文成长记录及勘误表
2.更多关于我
3.声明
1----本文由张风捷特烈原创,转载请注明
2----欢迎广大编程爱好者共同交流
3----个人能力有限,如有不正之处欢迎大家批评指证,必定虚心改正
4----看到这里,我在此感谢你的喜欢与支持
网友评论