您的位置:首页 > 移动开发 > Android开发

Android学习之旅(1)——XML的写入与解析

2020-02-17 02:06 429 查看

呀哈哈,今天端午节嘛,呀天气不错嘛,写篇文章记录一下!
今天是进公司的第一个礼拜的周末(端午节多放一天假哟^_^),闲着无聊……咳咳就写写这礼拜都做了些什么吧!
首先!公司用的是Ubuntu系统,对于我这个资深Windows症候群玩家来说,完全看不懂他在做什么啊!啊喂!咳咳算了这部分之后再说…..
先来讲讲礼拜五师傅让我做的一个Demo,XML的数据写入和解析(这只是一部分,剩下的数据库操作下周完成)。
正文开始:
1.既然是XML写入和解析,首先需要有对象!(咳咳单身狗别想歪了)
建立一个User对象(实体类),设置属性其属性
private int id;
private String name;
private String number;
private long date;//存储时间的毫秒数
2.设置一个List随便放点数据进去
users = new ArrayList();
users.add(new User(1,”张某某”,”15088888888”,System.currentTimeMillis()));
users.add(new User(2,”郭猴猴”,”18988888888”,System.currentTimeMillis()));
3.这里写一个方法用于将users转成XML输出至sd卡(记得给模拟器分配SD卡空间)

public void saveXML(List<User> users){
String sdState = Environment.getExternalStorageState();//sd卡状态
String path = Environment.getExternalStorageDirectory().toString();//sd卡根目录
if(sdState.equals(Environment.MEDIA_MOUNTED)){//如果sd卡可用
XmlSerializer serializer = Xml.newSerializer();//Xml输出类
File file = new File(path,"test01_sql.xml");//文件名自己取
FileOutputStream os;
try {
os = new FileOutputStream(file);
serializer.setOutput(os, "UTF-8");

serializer.startDocument("UTF-8", true);
serializer.startTag(null, "USERS");//设置标签
serializer.attribute(null, "xmlns", "http://test01_sql");//标签属性
for (User user : users) {//遍历所有user
serializer.startTag(null, "USER");//开始标签

serializer.startTag(null, "ID");
serializer.text(user.getid()+"");//标签之间的内容
serializer.endTag(null, "ID");

serializer.startTag(null, "NAME");
serializer.text(user.getName()+"");

4000
serializer.endTag(null, "NAME");

serializer.startTag(null, "NUMBER");
serializer.text(user.getNumber()+"");
serializer.endTag(null, "NUMBER");

serializer.startTag(null, "DATE");
serializer.text(user.getDate()+"");
serializer.endTag(null, "DATE");

serializer.endTag(null, "USER");//结束标签
}

serializer.endTag(null, "USERS");
serializer.endDocument();
os.close();
System.out.println("XML添加成功\n"+path+"/test01_sql.xml");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("XML添加失败");
}
}
}

4.检测一下XML是否生成成功

File f = new File(url);//url是文件路径
InputStream is;
if(f.exists()){
try {
is = new FileInputStream(f);
byte[] b = new byte[(int)f.length()];
is.read(b);
System.out.println(new String(b));//打印在控制台上
is.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

5.创建XML解析类(SAX解析)

public class XML_SAX extends DefaultHandler{
String element;//标签暂存
List<User> users;
User user;
StringBuffer jsonStringBuffer;
int frontBlankCount = 0;
public XML_SAX(){
jsonStringBuffer = new StringBuffer();
}
public List<User> getUsers(){
return users;
}
private String toBlankString(int count){
StringBuffer buffer = new StringBuffer();
for(int i = 0;i<count;i++)
buffer.append("    ");
return buffer.toString();
}
/*
* 接收字符数据的通知。
* 在DOM中 ch[begin:end] 相当于Text节点的节点值(nodeValue)
*/
@Override
public void characters(char[] ch, int begin, int length)
throws SAXException {
StringBuffer buffer = new StringBuffer();
for(int i = begin ; i < begin+length ; i++){
switch(ch[i]){
case '\\':buffer.append("\\\\");break;
case '\r':buffer.append("\\r");break;
case '\n':buffer.append("\\n");break;
case '\t':buffer.append("\\t");break;
case '\"':buffer.append("\\\"");break;
default : buffer.append(ch[i]);
}
}
if(element.equals("ID")){
user.setid(Integer.parseInt(buffer.toString()));
}else if(element.equals("NAME")){
user.setName(buffer.toString());
}else if(element.equals("NUMBER")){
user.setNumber(buffer.toString());
}else if(element.equals("DATE")){
user.setDate(Long.parseLong(buffer.toString()));
users.add(user);//date是最后一项
}
System.out.println(this.toBlankString(this.frontBlankCount)+
">>> characters("+length+"): "+buffer.toString());
}
/*
* 接收文档的结尾的通知。
*/
@Override
public void endDocument() throws SAXException {
System.out.println(this.toBlankString(--this.frontBlankCount)+
">>> end document");
}
/*
* 接收文档的结尾的通知。
* 参数意义如下:
*    uri :元素的命名空间
*    localName :元素的本地名称(不带前缀)
*    qName :元素的限定名(带前缀)
*
*/
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
System.out.println(this.toBlankString(--this.frontBlankCount)+
">>> end element : "+qName+"("+uri+")");
}
/*
* 结束前缀 URI 范围的映射。
*/
@Override
public void endPrefixMapping(String prefix) throws SAXException {
System.out.println(this.toBlankString(--this.frontBlankCount)+
">>> end prefix_mapping : "+prefix);
}
/*
* 接收可恢复的错误的通知
*/
@Override
public void error(SAXParseException e) throws SAXException {
System.err.println("Error ("+e.getLineNumber()+","
+e.getColumnNumber()+") : "+e.getMessage());
}

/*
* 接收不可恢复的错误的通知。
*/
@Override
public void fatalError(SAXParseException e) throws SAXException {
System.err.println("FatalError ("+e.getLineNumber()+","
+e.getColumnNumber()+") : "+e.getMessage());
}
/*
* 接收元素内容中可忽略的空白的通知。
* 参数意义如下:
*     ch : 来自 XML 文档的字符
*     start : 数组中的开始位置
*     length : 从数组中读取的字符的个数
*/
@Override
public void ignorableWhitespace(char[] ch, int begin, int length)
throws SAXException {
StringBuffer buffer = new StringBuffer();
for(int i = begin ; i < begin+length ; i++){
switch(ch[i]){
case '\\':buffer.append("\\\\");break;
case '\r':buffer.append("\\r");break;
case '\n':buffer.append("\\n");break;
case '\t':buffer.append("\\t");break;
case '\"':buffer.append("\\\"");break;
default : buffer.append(ch[i]);
}
}
System.out.println(this.toBlankString(
this.frontBlankCount)+">>> ignorable whitespace("+length+"): "+buffer.toString());
}
/*
* 接收注释声明事件的通知。
* 参数意义如下:
*     name - 注释名称。
*     publicId - 注释的公共标识符,如果未提供,则为 null。
*     systemId - 注释的系统标识符,如果未提供,则为 null。
*/
@Override
public void notationDecl(String name, String publicId, String systemId)
throws SAXException {
System.out.println(">>> notation declare : (name = "+name
+",systemId = "+publicId
+",publicId = "+systemId+")");
}
/*
* 接收处理指令的通知。
* 参数意义如下:
*     target : 处理指令目标
*     data : 处理指令数据,如果未提供,则为 null。
*/
@Override
public void processingInstruction(String target, String data)
throws SAXException {
System.out.println(this.toBlankString(this.frontBlankCount)+">>> process instruction : (target = \""
+target+"\",data = \""+data+"\")");
}
/*
* 允许应用程序解析外部实体。
* 解析器将在打开任何外部实体(顶级文档实体除外)前调用此方法
* 参数意义如下:
*     publicId : 被引用的外部实体的公共标识符,如果未提供,则为 null。
*     systemId : 被引用的外部实体的系统标识符。
* 返回:
*     一个描述新输入源的 InputSource 对象,或者返回 null,
*     以请求解析器打开到系统标识符的常规 URI 连接。
*/
@Override
public InputSource resolveEntity(String publicId, String systemId)
throws IOException, SAXException {
// TODO Auto-generated method stub
return null;
}
/*
* 接收用来查找 SAX 文档事件起源的对象。
* 参数意义如下:
*     locator : 可以返回任何 SAX 文档事件位置的对象
*/
@Override
public void setDocumentLocator(Locator locator) {
System.out.println(this.toBlankString(this.frontBlankCount)+
">>> set document_locator : (lineNumber = "+locator.getLineNumber()

1a4bc
+",columnNumber = "+locator.getColumnNumber()
+",systemId = "+locator.getSystemId()
+",publicId = "+locator.getPublicId()+")");
}
/*
* 接收跳过的实体的通知。
* 参数意义如下:
*     name : 所跳过的实体的名称。如果它是参数实体,则名称将以 '%' 开头,
*            如果它是外部 DTD 子集,则将是字符串 "[dtd]"
*/
@Override
public void skippedEntity(String name) throws SAXException {
System.out.println(this.toBlankString(this.frontBlankCount)+
">>> skipped_entity : "+name);
}
/*
* 接收文档的开始的通知。
*/
@Override
public void startDocument() throws SAXException {
System.out.println(this.toBlankString(this.frontBlankCount++)+
">>> start document ");
}
/*
* 接收元素开始的通知。
* 参数意义如下:
*    uri :元素的命名空间
*    localName :元素的本地名称(不带前缀)
*    qName :元素的限定名(带前缀)
*    atts :元素的属性集合
*/
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if(qName.equals("USERS")){
users = new ArrayList<User>();
}else if(qName.equals("USER")){
user = new User();
}else if(qName.equals("ID")||qName.equals("NAME")||
qName.equals("NUMBER")||qName.equals("DATE") ){
element = qName;
}
System.out.println(this.toBlankString(this.frontBlankCount++)+
">>> start element : "+qName);
}
/*
* 开始前缀 URI 名称空间范围映射。
* 此事件的信息对于常规的命名空间处理并非必需:
* 当 http://xml.org/sax/features/namespaces 功能为 true(默认)时,
* SAX XML 读取器将自动替换元素和属性名称的前缀。
* 参数意义如下:
*    prefix :前缀
*    uri :命名空间
*/
@Override
public void startPrefixMapping(String prefix, String uri)
throws SAXException {
System.out.println(this.toBlankString(this.frontBlankCount++)+
">>> start prefix_mapping : xmlns:"
+"\""+uri+"\"");
}
/*
* 接收未解析的实体声明事件的通知。
* 参数意义如下:
*     name - 未解析的实体的名称。
*     publicId - 实体的公共标识符,如果未提供,则为 null。
*     systemId - 实体的系统标识符。
*     notationName - 相关注释的名称。
*/
@Override
public void unparsedEntityDecl(String name, String publicId,
String systemId, String notationName) throws SAXException {
System.out.println(">>> unparsed entity declare : (name = "+name
+",systemId = "+publicId
+",publicId = "+systemId
+",notationName = "+notationName+")");
}
/*
* 接收不可恢复的错误的通知。
*/
@Override
public void warning(SAXParseException e) throws SAXException {
System.err.println("Warning ("+e.getLineNumber()+","
+e.getColumnNumber()+") : "+e.getMessage());
}

}

简单来说就是继承了DefaultHandler,重写其方法,其中方法会将XML内容提取出来,大家稍微运行下代码就看得懂了,输出是有层次的。
期间我还将解析出来的数据存在了List里在使用解析时可以将User内容输出(为了数据库操作准备的)

6.使用XML解析类

System.setProperty("org.xml.sax.driver","org.xmlpull.v1.sax2.Driver"); //运行之前需要注册 Sax 驱动(android中需要)
XML_SAX dh = new XML_SAX(); //创建处理xml的处理器
XMLReader reader;//创建一个XML解析器(通过SAX方式读取解析XML)
try {
reader = XMLReaderFactory.createXMLReader();
/*
* 设置解析器的相关特性
*     http://xml.org/sax/features/validation = true 表示开启验证特性
*     http://xml.org/sax/features/namespaces = true 表示开启命名空间特性
*/
reader.setFeature("http://xml.org/sax/features/validation",true);
reader.setFeature("http://xml.org/sax/features/namespaces",true);
//设置XML解析器的处理器
reader.setDTDHandler(dh);
reader.setContentHandler(dh);
reader.setEntityResolver(dh);
reader.setErrorHandler(dh);
//解析url对应的xml文档
System.out.println("开始解析");
reader.parse(new InputSource(new FileReader(url)));
System.out.println("解析结束");
List<User> users_x = dh.getUsers();
for (User use_x : users_x) {
System.out.println("User:"+use_x.getid()+":"+use_x.getName()+":"+use_x.getNumber()+":"+use_x.getDate());
}//输出XML中的User中的属性

} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

总结:
基本就是这样了吧!应该没啥问题!第一次写这种东西!咳咳。。。!我没紧张!那下次再给大家继续吐槽!谢谢大家!
(啊喂!好像有人看一样!(σ`д′)σ(゚Д゚*)ノ)

  • 点赞
  • 收藏
  • 分享
  • 文章举报
yyf123yyf11 发布了1 篇原创文章 · 获赞 0 · 访问量 205 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: