Android中的XML解析

什么是XML

  • XML 指可扩展标记语言
  • XML 被设计用来传输和存储数据
  • XML 需要自定义标签
  • XML 必须有一个跟元素,该元素是其他元素的父元素
  • XML 对大小写敏感

XML的用途

  • XML 把数据从 HTML 分离
  • XML 简化数据共享
  • XML 简化数据传输
  • XML 简化平台的变更
  • XML 使您的数据更有用
  • XML 用于创建新的 Internet 语言

XML语法规则

  • 所有 XML 元素都须有关闭标签
  • XML 标签对大小写敏感
  • XML 必须正确地嵌套
  • XML 文档必须有根元素
  • 在 XML 中,空格会被保留
  • XML 以 LF 存储换行
  • XML 的属性值须加引号
  • 实体引用

在 XML 中,有 5 个预定义的实体引用:

< < 小于
> > 大于
& & 和号
' ' 单引号
" " 引号

常用的XML解析

常用的解析XML的方式有三种,分别为:

  • DOM

    DOM解析XML在J2EE中比较常见,在DOM解析过程中,是先把XML文件全部读取到内存中,然后使用DOM的API遍历所有数据,检索想要的数据
    这种做法的缺点是耗费内存,对于像手机这类的移动设备来说,较大的XML文件显然不适合使用DOM解析。
    这种做法的优点是比较直观,在XML文件比较小的时候可以使用
  • Pull

    PULL提供了开始元素和结束元素。当某个元素开始时,可以调用parser.nextText()从XML文档中提取所有字符数据,当解析到一个文档结束时,自动生成EndDocument事件
  • SAX

    SAX是一个解析速度快并且占用内存少的xml解析器,非常适合用于Android等移动设备。
    SAX解析XML文件采用的是事件驱动,也就是说,它并不需要解析完整个文档。
    在按内容顺序解析文档的过程中,SAX会判断当前读到的字符是否合法XML语法中的某部分,如果符合就会触发事件。

DOM方式处理XML

DOM写数据

DOM方式写XML文件大致可归纳为如下几步:

  1. 利用DocumentBuilderFactory创建一个DocumentBuilderFactory实例
  2. 利用DocumentBuilderFactory创建DocumentBuilder
  3. 利用DocumentBuilder创建Document文件
  4. 创建根节点
  5. 将根节点添加到Document中
  6. 利用循环将数据添加到Document中
  7. 使用TransformerFactory创建一个TransformerFactory对象
  8. 使用TransformerFactory对象创建一个新的事务
  9. 创建DOMSource
  10. 创建文件

示例代码:

public class MainActivity extends Activity { 
 
    private List list = new ArrayList(); 
 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.activity_main); 
 
        addData(); 
 
        try { 
            // 利用DocumentBuilderFactory创建一个DocumentBuilderFactory实例 
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
            // 利用DocumentBuilderFactory创建DocumentBuilder 
            DocumentBuilder builder = factory.newDocumentBuilder(); 
            // 利用DocumentBuilder创建Document文件 
            Document document = builder.newDocument(); 
            // 创建根节点 
            Element rootElement = document.createElement("students"); 
            // 将根节点添加到Document中 
            document.appendChild(rootElement); 
            // 利用循环将数据添加到Document中 
            for (int i = 0; i < list.size(); i++) { 
                int id = list.get(i).getId(); 
                String name = list.get(i).getName(); 
                int age = list.get(i).getAge(); 
                String sex = list.get(i).getSex(); 
                Element studentElement = document.createElement("student"); 
                studentElement.setAttribute("id", id + ""); 
                Element nameElement = document.createElement("name"); 
                nameElement.setTextContent(name); 
                Element ageElement = document.createElement("age"); 
                ageElement.setTextContent(age + ""); 
                Element sexElement = document.createElement("sex"); 
                sexElement.setTextContent(sex); 
 
                studentElement.appendChild(nameElement); 
                studentElement.appendChild(ageElement); 
                studentElement.appendChild(sexElement); 
 
                rootElement.appendChild(studentElement); 
 
            } 
            // 创建TransformerFactory实例 
            TransformerFactory tf = TransformerFactory.newInstance(); 
            // 创建事务对象 
            Transformer transformer = tf.newTransformer(); 
            // 创建DOMSource 
            DOMSource source = new DOMSource(document); 
            // 创建文件存放在 /data/data/cn.xxx.xxx(当前包)/files 
            FileOutputStream fos = openFileOutput("Dom.xml", Context.MODE_PRIVATE); 
            PrintWriter pw = new PrintWriter(fos); 
            StreamResult result = new StreamResult(pw); 
            // 使用事务的transform方法写入文件 
            transformer.transform(source, result); 
 
        } catch (ParserConfigurationException e) { 
            // TODO Auto-generated catch block 
            e.printStackTrace(); 
        } catch (TransformerConfigurationException e) { 
            // TODO Auto-generated catch block 
            e.printStackTrace(); 
        } catch (TransformerException e) { 
            // TODO Auto-generated catch block 
            e.printStackTrace(); 
        } catch (FileNotFoundException e) { 
            // TODO Auto-generated catch block 
            e.printStackTrace(); 
        } 
 
    } 
 
    private void addData() { 
        list.add(new Student(1, "刘德华", 50, "男")); 
        list.add(new Student(2, "郭富城", 60, "男")); 
        list.add(new Student(3, "林志玲", 40, "女")); 
        list.add(new Student(4, "高圆圆", 40, "女")); 
        list.add(new Student(5, "张学友", 53, "男")); 
        list.add(new Student(6, "孙燕姿", 30, "女")); 
    } 
}

创建的XML文件:

<?xml version="1.0" encoding="UTF-8"?> 
<students> 
    <student id="1"> 
        <name>刘德华</name> 
        <age>50</age> 
        <sex>男</sex> 
    </student> 
    <student id="2"> 
        <name>郭富城</name> 
        <age>60</age> 
        <sex>男</sex> 
    </student> 
    <student id="3"> 
        <name>林志玲</name> 
        <age>40</age> 
        <sex>女</sex> 
    </student> 
    <student id="4"> 
        <name>高圆圆</name> 
        <age>40</age> 
        <sex>女</sex> 
    </student> 
    <student id="5"> 
        <name>张学友</name> 
        <age>53</age> 
        <sex>男</sex> 
    </student> 
    <student id="6"> 
        <name>孙燕姿</name> 
        <age>30</age> 
        <sex>女</sex> 
    </student> 
</students> 

DOM读数据

DOM方式读XML文件大致可归纳为如下几步:

  1. 利用DocumentBuilderFactory创建一个DocumentBuilderFactory实例
  2. 利用DocumentBuilderFactory创建DocumentBuilder
  3. 使用openFileInput来读取XML文件
  4. 调用DocumentBuilder的parse()方法完成解析XML,这步执行完成之后,XML暂存在内存中
  5. 通过DocumentBuilder的getDocumentElement()方法获取XML的根节点
  6. 通过根节点的getElementsByTagName()方法获取根节点中所有子节点列表
  7. 通过循环+getElementsByTagName获取子节点列表中需要读取的节点

示例代码:

public class MainActivity extends Activity { 
 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.activity_main); 
 
        try { 
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
            DocumentBuilder builder = factory.newDocumentBuilder(); 
            FileInputStream fis = openFileInput("Dom.xml"); 
            Document document = builder.parse(fis); 
            Element rootElement = document.getDocumentElement(); 
            NodeList element = rootElement.getElementsByTagName("student"); 
 
            for (int i = 0; i < element.getLength(); i++) { 
                Element node = (Element) element.item(i); 
                String id = node.getAttribute("id"); 
                String name = node.getElementsByTagName("name").item(0).getTextContent(); 
                int age = Integer.parseInt(node.getElementsByTagName("age").item(0).getTextContent()); 
                String sex = node.getElementsByTagName("sex").item(0).getTextContent(); 
                Log.d("TTTT", "id=" + id + ",name=" + name + ",age=" + age + ",sex=" + sex); 
            } 
        } catch (ParserConfigurationException e) { 
            // TODO Auto-generated catch block 
            e.printStackTrace(); 
        } catch (FileNotFoundException e) { 
            // TODO Auto-generated catch block 
            e.printStackTrace(); 
        } catch (SAXException e) { 
            // TODO Auto-generated catch block 
            e.printStackTrace(); 
        } catch (IOException e) { 
            // TODO Auto-generated catch block 
            e.printStackTrace(); 
        } 
 
    } 
} 

PULL方式处理XML

PULL写数据

PULL提供了开始元素和结束元素。当某个元素开始时,可以调用parser.nextText()从XML文档中提取所有字符数据,当解析到一个文档结束时,自动生成EndDocument事件。

类和接口 功能
XmlPullParser 该解析器是一个在org.xmlpull.v1中定义的解析功能的接口。
XmlSerializer 它是一个接口,定义了XML信息集的序列。
XmlPullParserFactory 这个类用于在XMPULL V1 API中创建XML Pull解析器。
XmlPullParserException 抛出单一的XML pull解析器相关的错误。

PULL提供了开始元素和结束元素。

当某个元素开始时,可以调用parser.nextText()从XML文档中提取所有字符数据,当解析到一个文档结束时,自动生成EndDocument事件。

如:开始元素和结束元素事件,使用parser.next()可以进入下一个元素并触发相应事件。事件将作为数值代码被发送,因此可以使用一个switch对感兴趣的事件进行处理。当元素开始解析时,调用parser.nextText()方法可以获取下一个Text类型元素的值。

  • START_DOCUMENT

    读取到xml时的声明
  • END_DOCUMENT

    结束时返回
  • START_TAG

    开始标签时返回
  • END_TAG

    结束标签时返回

示例代码:

public class MainActivity extends Activity { 
 
    private List list = new ArrayList(); 
 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.activity_main); 
 
        dataInList(); 
 
        try { 
            FileOutputStream fos = openFileOutput("pull.xml", MODE_PRIVATE); 
            XmlSerializer xmlSerializer = Xml.newSerializer(); 
            xmlSerializer.setOutput(fos, "UTF-8"); 
 
            xmlSerializer.startTag(null, "students"); 
 
            for (Student student : list) { 
                xmlSerializer.startTag(null, "student"); 
                xmlSerializer.attribute(null, "id", student.getId() + ""); 
 
                xmlSerializer.startTag(null, "name"); 
                xmlSerializer.text(student.getName()); 
                xmlSerializer.endTag(null, "name"); 
 
                xmlSerializer.startTag(null, "age"); 
                xmlSerializer.text(student.getAge() + ""); 
                xmlSerializer.endTag(null, "age"); 
 
                xmlSerializer.startTag(null, "sex"); 
                xmlSerializer.text(student.getSex()); 
                xmlSerializer.endTag(null, "sex"); 
 
                xmlSerializer.endTag(null, "student"); 
            } 
 
            xmlSerializer.endTag(null, "students"); 
            xmlSerializer.endDocument(); 
 
        } catch (FileNotFoundException e) { 
            // TODO Auto-generated catch block 
            e.printStackTrace(); 
        } catch (IllegalArgumentException e) { 
            // TODO Auto-generated catch block 
            e.printStackTrace(); 
        } catch (IllegalStateException e) { 
            // TODO Auto-generated catch block 
            e.printStackTrace(); 
        } catch (IOException e) { 
            // TODO Auto-generated catch block 
            e.printStackTrace(); 
        } 
    } 
 
    private void dataInList() { 
        list.add(new Student(1, "张一", 10, "男")); 
        list.add(new Student(2, "张二", 20, "女")); 
        list.add(new Student(3, "张三", 30, "男")); 
        list.add(new Student(4, "张四", 40, "女")); 
        list.add(new Student(5, "张五", 50, "男")); 
        list.add(new Student(6, "张六", 60, "女")); 
    } 
} 

PULL读数据

利用pull解析XML文件需要下面几个步骤:

  1. 通过XMLPullParserFactory获取XMLPullParser对象。
  2. 通过XMLPullParser对象设置输入流。
  3. 通过parser.next(),持续的解析XML文件直到文件的尾部。

示例代码:

public class MainActivity extends Activity { 
 
    private List studentList = new ArrayList(); 
    private Student student = null; 
 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.activity_main); 
 
        try { 
            FileInputStream fis = openFileInput("pull.xml"); 
 
            // 1.使用android提供的Xml类new一个XmlPullerParser,即new一个XmlPull解析器 
            XmlPullParser xmlPullParser = Xml.newPullParser(); 
 
            // 2.然后设置需要解析的xml文件,第一个参数为输入流,第二个参数为字符编码 
            xmlPullParser.setInput(fis, "UTF-8"); 
 
            // 3.触发事件,当这个方法遇到某个字符符合XML语法,就会触发这个语法所代表的数字 
            int event = xmlPullParser.getEventType(); 
 
            // 4.XML文件的第一行为开始文档事件START_DOCUMENT,最后一行为结束文档事件END_DOCUMENT,我们需要不断读取xml文件的内容 
            while (event != xmlPullParser.END_DOCUMENT) { 
 
                // 5.我们对这个事件进行处理,我们感兴趣的是这个元素 
                switch (event) { 
                case XmlPullParser.START_TAG:// 6.如果这个事件是开始元素(例如)事件 
                    if (xmlPullParser.getName().equals("student")) { 
                        student = new Student(); 
                        // 7.使用解析器得到当前元素的属性,即id 
                        int id = Integer.parseInt(xmlPullParser.getAttributeValue(0)); 
                        student.setId(id); 
                    } else if (xmlPullParser.getName().equals("name")) { 
                        // 8.如果当前元素为开始标签,下一个元素为文本,就会返回这个文本 
                        student.setName(xmlPullParser.nextText()); 
                    } else if (xmlPullParser.getName().equals("age")) { 
                        // 8.如果当前元素为开始标签,下一个元素为文本,就会返回这个文本 
                        student.setAge(Integer.parseInt(xmlPullParser.nextText())); 
                    } else if (xmlPullParser.getName().equals("sex")) { 
                        // 8.如果当前元素为开始标签,下一个元素为文本,就会返回这个文本 
                        student.setSex(xmlPullParser.nextText()); 
                    } 
                    break; 
 
                case XmlPullParser.END_TAG:// 9.如果这个事件是结束元素(例如)事件 
                    if ("student".equals(xmlPullParser.getName())) { 
                        studentList.add(student); 
                    } 
                    break; 
                } 
                event = xmlPullParser.next(); 
            } 
 
            for (Student student : studentList) { 
                Log.d("TTTT", "id:" + student.getId() + ",name:" + student.getName() + ",age:" + student.getAge() 
                        + ",sex:" + student.getSex()); 
            } 
 
        } catch (FileNotFoundException e) { 
            // TODO Auto-generated catch block 
            e.printStackTrace(); 
        } catch (XmlPullParserException e) { 
            // TODO Auto-generated catch block 
            e.printStackTrace(); 
        } catch (IOException e) { 
            // TODO Auto-generated catch block 
            e.printStackTrace(); 
        } 
    } 
} 

SAX方式解析XML

SAX是一个解析速度快并且占用内存少的xml解析器,非常适合用于Android等移动设备。SAX解析XML文件采用的是事件驱动,也就是说,它并不需要解析完整个文档。

在按内容顺序解析文档的过程中,SAX会判断当前读到的字符是否合法XML语法中的某部分,如果符合就会触发事件。

所谓事件,其实就是一些回调(callback)方法,这些方法(事件)定义在ContentHandler接口。

下面是一些ContentHandler接口常用的方法:

  • startDocument()

    当遇到文档的开头的时候,调用这个方法,可以在其中做一些预处理的工作。
  • endDocument()

    和上面的方法相对应,当文档结束的时候,调用这个方法,可以在其中做一些善后的工作。
  • startElement(String namespaceURI, String localName, String qName, Attributes atts)

    当读到一个开始标签的时候,会触发这个方法。

    • namespaceURI

      命名空间
    • localName

      不带命名空间前缀的标签名
    • qName

      带命名空间前缀的标签名
    • atts

      通过atts可以得到所有的属性名和相应的值
  • endElement(String uri, String localName, String name)

    这个方法和上面的方法相对应,在遇到结束标签的时候,调用这个方法。
  • characters(char[] ch, int start, int length)

    这个方法用来处理在XML文件中读到的内容,第一个参数为文件的字符串内容,后面两个参数是读到的字符串在这个数组中的起始位置和长度,使用new String(ch,start,length)就可以获取内容。

要注意的是SAX中一个重要的特点就是它的流式处理,当遇到一个标签的时候,它并不会纪录下以前所碰到的标签,也就是说,在startElement()方法中,所有你所知道的信息,就是标签的名字和属性,至于标签的嵌套结构,上层标签的名字,是否有子元属等等其它与结构相关的信息,都是不得而知的,都需要你的程序来完成。这使得SAX在编程处理上没有DOM来得那么方便。

SAX写数据

public class MainActivity extends Activity { 
 
    private List list = new ArrayList(); 
 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.activity_main); 
        dataInList(); 
 
        try { 
            FileOutputStream fos = openFileOutput("sax.xml", MODE_PRIVATE); 
 
            SAXTransformerFactory saxTransformerFactory = (SAXTransformerFactory) SAXTransformerFactory.newInstance(); 
            TransformerHandler transformerHandler = saxTransformerFactory.newTransformerHandler(); 
            Transformer transformer = transformerHandler.getTransformer(); 
 
            // 设置XML的格式 
            transformer.setOutputProperty(OutputKeys.INDENT, "yes"); // 是否缩进 
            transformer.setOutputProperty(OutputKeys.ENCODING, "utf-8"); // 字符集 
            transformer.setOutputProperty(OutputKeys.VERSION, "1.0"); // 版本号 
 
            transformerHandler.setResult(new StreamResult(fos)); 
 
            transformerHandler.startDocument(); 
 
            AttributesImpl attributesImpl = new AttributesImpl(); 
 
            attributesImpl.clear(); 
            transformerHandler.startElement("", "", "students", attributesImpl); 
 
            for (Student student : list) { 
                attributesImpl.clear(); 
                attributesImpl.addAttribute("", "", "id", "", student.getId() + ""); 
                transformerHandler.startElement("", "", "student", attributesImpl); 
 
                attributesImpl.clear(); 
                transformerHandler.startElement("", "", "name", attributesImpl); 
                transformerHandler.characters(student.getName().toCharArray(), 0, student.getName().length()); 
                transformerHandler.endElement("", "", "name"); 
 
                attributesImpl.clear(); 
                transformerHandler.startElement("", "", "age", attributesImpl); 
                transformerHandler.characters((student.getAge() + "").toCharArray(), 0, 
                        (student.getAge() + "").length()); 
                transformerHandler.endElement("", "", "age"); 
 
                attributesImpl.clear(); 
                transformerHandler.startElement("", "", "sex", attributesImpl); 
                transformerHandler.characters(student.getSex().toCharArray(), 0, student.getSex().length()); 
                transformerHandler.endElement("", "", "sex"); 
 
                transformerHandler.endElement("", "", "student"); 
            } 
            transformerHandler.endElement("", "", "students"); 
            transformerHandler.endDocument(); 
 
        } catch (FileNotFoundException e) { 
            // TODO Auto-generated catch block 
            e.printStackTrace(); 
        } catch (TransformerConfigurationException e) { 
            // TODO Auto-generated catch block 
            e.printStackTrace(); 
        } catch (SAXException e) { 
            // TODO Auto-generated catch block 
            e.printStackTrace(); 
        } 
    } 
 
    private void dataInList() { 
        list.add(new Student(1, "张一", 10, "男")); 
        list.add(new Student(2, "张二", 20, "女")); 
        list.add(new Student(3, "张三", 30, "男")); 
        list.add(new Student(4, "张四", 40, "女")); 
        list.add(new Student(5, "张五", 50, "男")); 
        list.add(new Student(6, "张六", 60, "女")); 
    } 
} 

SAX读数据

解析SAX我们通常会创建一个继承自DefaultHandler,并重写父类的几个方法

  • public void setDocumentLocator(Locator locator)

    设置一个可以定位文档内容事件发生位置的定位器对象
  • public void startDocument()throws SAXException

    用于处理文档解析开始事件
  • public void startElement(String namespacesURI , String localName , String qName , Attributes atts) throws SAXException

    处理元素开始事件,从参数中可以获得元素所在名称空间的uri,元素名称,属性类表等信息
  • public void endElement(String namespacesURI , String localName , String qName) throws SAXException

    处理元素结束事件,从参数中可以获得元素所在名称空间的uri,元素名称等信息
  • public void characters(char[] ch , int start , int length) throws SAXException

    处理元素的字符内容,从参数中可以获得内容

SAX实现实体解析的步骤:

在android中使用SAX是有迹可循的,完全可以按照下面的方法就可以轻松找到xml里的tag,然后得到想要的内容。具体实现步骤如下:

  • 新建一个工厂类SAXParserFactory
SAXParserFactory factory = SAXParserFactory.newInstance();
  • 让工厂类产生一个SAX的解析类SAXParser
SAXParser parser = factory.newSAXParser();
  • 从SAXPsrser中得到一个XMLReader实例
XMLReader reader = parser.getXMLReader();
  • 把自己写的handler注册到XMLReader中,一般最重要的就是ContentHandler
RSSHandler handler = new RSSHandler();
reader.setContentHandler(handler);
  • 将一个xml文档或者资源变成一个java可以处理的InputStream流后,解析正式开始
parser.parse(is);

示例代码:

MainActivity.java

public class MainActivity extends Activity { 
 
    private List list = new ArrayList(); 
 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.activity_main); 
 
        try { 
            FileInputStream fis = openFileInput("sax.xml"); 
            MyXMLHandler handler = new MyXMLHandler(); 
            SAXParserFactory factory = SAXParserFactory.newInstance(); 
            SAXParser parser = factory.newSAXParser(); 
            parser.parse(fis, handler); 
            fis.close(); 
             
            ArrayList list = (ArrayList) handler.getList(); 
            for (Student student : list) { 
                Log.d("TTTT", "id:" + student.getId() + ",name:" + student.getName() + ",age:" + student.getAge() 
                        + ",sex:" + student.getSex()); 
            } 
 
        } catch (FileNotFoundException e) { 
            // TODO Auto-generated catch block 
            e.printStackTrace(); 
        } catch (ParserConfigurationException e) { 
            // TODO Auto-generated catch block 
            e.printStackTrace(); 
        } catch (SAXException e) { 
            // TODO Auto-generated catch block 
            e.printStackTrace(); 
        } catch (IOException e) { 
            // TODO Auto-generated catch block 
            e.printStackTrace(); 
        } 
 
    } 
} 

MyXMLHandler.java

public class MyXMLHandler extends DefaultHandler { 
 
    private ArrayList list; 
    private Student student; 
    private String tagName; 
 
    public List getList() { 
        return list; 
    } 
 
    @Override 
    public void characters(char[] ch, int start, int length) throws SAXException { 
        // TODO Auto-generated method stub 
        super.characters(ch, start, length); 
        // Log.d("TTTT", "根据tagName获取标签的内容"); 
        if (tagName != null) { 
            String data = new String(ch, start, length); 
            if (tagName.equals("name")) { 
                student.setName(data); 
            } else if (tagName.equals("age")) { 
                student.setAge(Integer.valueOf(data.trim())); 
            } else if (tagName.equals("sex")) { 
                student.setSex(data); 
            } 
        } 
    } 
 
    @Override 
    public void endDocument() throws SAXException { 
        // TODO Auto-generated method stub 
        super.endDocument(); 
        Log.d("TTTT", "解析XML结束"); 
    } 
 
    @Override 
    public void endElement(String uri, String localName, String qName) throws SAXException { 
        // TODO Auto-generated method stub 
        super.endElement(uri, localName, qName); 
        if (localName.equals("student")) { 
            list.add(student); 
        } 
        tagName = null; 
    } 
 
    @Override 
    public void startDocument() throws SAXException { 
        // TODO Auto-generated method stub 
        super.startDocument(); 
        list = new ArrayList(); 
        Log.d("TTTT", "解析XML开始"); 
    } 
 
    @Override 
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { 
        // TODO Auto-generated method stub 
        super.startElement(uri, localName, qName, attributes); 
        Log.d("TTTT", "读取标签"); 
        this.tagName = localName; 
        if ("student".equals(tagName)) { 
            student = new Student(); 
            student.setId(Integer.parseInt(attributes.getValue(0))); 
            Log.d("TTTT", "id:" + attributes.getValue(0)); 
        } 
    } 
}