JAVA中的XML文件--文件读取(上)

菜鸟一只,最近一直在慕课网上学习java,结合自己的理解并且在网上查找相关讲解,将自己的学习笔记整理出来与大家分享一下,菜鸟就能不断进步。

1 XML文件简介

XML是可扩展标记语言(Extensible Markup Language)的缩写,其中Markup是关键部分,可以创建内容,然后使用限定标记标记它,从而使每个单词、短语或块成为可识别、可分类的信息。

1.1 XML文件是以树形结构存储

<根元素名称>
<子元素名 属性 = "属性值"
          ……    ……>
        <子元素名>****</子元素名>

        ……  ……  ……

        <子元素名>****</子元素名>
    </子元素名>

    …… …… ……

</根元素名称>

PS:
1. 相同元素名的不同元素属性和其子元素可以不同.
2. XML 文件由内容和标记组成,将内容文本包含到元素中,即分别在文本的首末两端添加开始和结束标记<元素名>文本

1.2 在XML文件首行声明–可选部分

它将文件识别为 XML 文件,有助于工具和人类识别XML,这个声明必须出现在文件的开头

<?xml version = "1.0" encoding = 编码格式(eg."UTF-8")?>

1.3 用途

解决不同程序、不同平台、不同操作系统的通讯问题。

2 JAVA中解析XML文件

在java中有四种解析XML文件的方式:DOM,SAX,DOM4J,JDOM。前两个是官方提供的,不需要额外的jar包
以student.xml文件为例:

<?xml version = "1.0" encoding = "UTF-8" ?>
<school>
    <student id = "0001">
        <name>王明</name>
        <sex></sex>
        <major>计算机科学与技术</major>
    </student>
    <student id = "0002">
        <name>李红</name>
        <sex></sex>
        <major>计算数学</major>
    </student>
</school>

2.1 应用DOM方式解析XML

2.1.1 准备工作

  • 创建一个DocumentBuilderFactory对象:
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

  • 创建一个DocumentBuilder对象:
    DocumentBuilder db = dbf.newDocumentBuilder()

  • 通过DocumentBuilder对象的parse方法加载xml文件到当前项目中:
    Document document = db.parse("*****.xml");

说明:
1. newInstance()是DocumentBuilderFactory的静态方法,用于获取DocumentBuilderFactory的一个实例;
2. newDocumentBuilder()用于获取DocumentBuilder的对象;
3. parse()方法是org.w3c.dom中的方法;
4. 注意捕捉异常。

2.1.2 获取元素(元素)的属性名和属性值

  • Document中的getElementByTagName(“student”)方法根据给定的元素名来获取该元素组成的集合,返回为NodeList类型(stuList):
    NodeList stuList = document.getElementByTagName("student");

  • 通过item(int index)方法遍历stuList中的每个元素,返回Node类型:
    Node stu = stuList.item(i);

  • 获得了每个元素后就可以获得进一步得到每个元素的属性,通过getAttributes()方法获得一个所有属性和属性值的映射NamedNodeMap:
    NamedNodeMap attr = stu.getAtrributes();

  • 同样的,属性映射attr通过item(index)方法获得每个属性,显然将返回一个Node类型:
    Node attrnode = atts.item(i);
    这时我们要进一步得到每个属性(attrnode)的名字和属性值,分别通过getNodeName()和getNodeValue()方法。

  • 同时,注意到元素student除了有属性外,还有许多子元素(name,major等),如何获取呢?
    通过getChildNodes()方法获取子元素的集合,和前面类似,返回值也是NodeList类型。每个元素中包含的文本也被看作是该元素的子元素,获取每个元素包含的文本可以通过getNodeValue()方法获取。

备注:
1. 常用的元素类型:

类型NodeTypeNamed ConstantnodeName/nodeValue
Element1ELEMENT_NODEelement name / null
Attr2ATTRIBUTE_NODEattribute name / attribute value
Text3TEXT_NODEtext / node text

由标记包含的元素(school、student、name等)的类型就是Element,元素的属性就是Attr类型,元素中的文本内容和xml元素间的空格等就是Text类型
2. 因为空格也会被看作是元素,所以获取我们所需要的元素时,应注意避免获取空格,我们可以通过判断得到的元素类型来避免空格:
node.getNodeType() == Node.ELEMENT_NODE;
3. 获取每个元素中的文本也可通过getTextContext()方法,它返回的是包括子元素的所有文本。
4. 可通过getFirstChild()方法获取元素的第一个子元素,可以和getTextContext()搭配使用。

2.1.3 代码示例如下:

public class DomTest {

    public static void main(String[] args) {
        //创建一个DocumentBuilderFactory对象
        DocumentBuilderFactory dbf =  DocumentBuilderFactory.newInstance();
        try {
            //创建一个DocumentBuilder对象
            DocumentBuilder db = dbf.newDocumentBuilder();
            //通过DocumentBuilder对象的parse方法加载books.xml到当前项目下
            Document document = db.parse("students.xml");
            //根据节点名获取所有该节点的集合
            NodeList stuList = document.getElementsByTagName("student");
            System.out.println("一共有"+stuList.getLength()+"个学生");
            //遍历每一个student节点
            for(int i = 0;i < stuList.getLength();++ i){
                //通过item(i)方法获取一个节点
                Node book = stuList.item(i);
                NamedNodeMap atts =book.getAttributes();
                System.out.println("第"+(i+1)+"个学生共有"+atts.getLength()+"个属性");
                for(int j = 0; j < atts.getLength(); ++ j){
                    Node node = atts.item(j);
                    System.out.println(
                    node.getNodeName()+","+node.getNodeValue());
                }
                NodeList childNodes = book.getChildNodes();
                System.out.println("共有"+childNodes.getLength()+"个子节点");
                for(int j = 0;j < childNodes.getLength();++ j)
                {
                    Node node = childNodes.item(j);
                    //区分出text类型的node以及element类型中的node
                    if(node.getNodeType() == Node.ELEMENT_NODE){
                        //获取element类型节点的节点名的三种方式                        
                        System.out.println( node.getNodeName()+","+
                            node.getChildNodes().item(0).getNodeValue());
                        System.out.println(node.getNodeName()+","+
                            node.getFirstChild().getNodeValue());                       
                        System.out.println(node.getNodeName()+","+  
                            node.getFirstChild().getTextContent());
                    }
                }
            }
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        }catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2.2 应用SAX方式解析XML

SAX方式是通过DefaultHanlder逐行扫描XML文件内容,文档的读入过程也就是SAX的解析过程。

2.2.1 准备工作

  • 使用SAXParserFactory的静态方法newInstance()获取 SAXParserFactory实例:
    SAXParserFactory factory = SAXParserFactory.newInstance();

  • 通过factory.newSAXParser()方法获取SAXParser实例:
    SAXParser parser = factory.newSAXParser();

  • 用parse()方法解析XML文件:
    parser.parse("student.xml",DefaultHandler handler)

  • 上一步中,我们需要一个DefaultHandler参数:
    创建一个类继承DefaultHandler,重写其中的一些方法,进行业务处理并创建这个类的实例传给parse()方法
    public class SAXParserHandler extends DefaultHandler

2.2.2 获取元素文本

在handler类中会重写如下几个方法:

  • startDocument()方法,文件解析开始使调用;

  • endDocument()方法,文件解析结束时调用;

  • startElement(String uri, String localName, String qName, Attributes attrs)方法

    变量名表示
    qName当前访问的元素名
    attrs元素的属性

    每访问一个元素都会调用该方法,如上表所述,qName可以得到 当前访问元素名,attrs保存了该元素的属性集合,可以通过getQName(index)和getQValue(index)方法遍历属性。

  • endElement(String uri, String localName, String qName)方法,当某个元素访问结束后调用;

  • characters(char[] ch, int start, int length)方法中,ch变量保存了整个xml文件内容,而start和length表示了当前访问元素文本的开始位置和长度,从而可将每个元素的文本内容保存到字符串中(根据程序执行结果,调用该方法是根据每个元素中文本和子元素的顺序调用的,如下代码的顺序:aaa ->root ->bbb)

    <root>
        <a>aaa</a>
        root
        <b>bbb</b>
    <root>

    但是需注意空格也将被看作子元素,所以应将全是空格的字符串筛选掉,可用trim()方法删除字符串左右两边的空格,然后判断剩余字符串是否是空(equals(“”))。

备注:
1.注意以上方法将抛出异常

不断学习不断总结^_^。。。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值