解析xml文件

本文介绍了XML的基本概念及其与HTML的区别,并详细阐述了如何使用DOM和dom4j解析XML文件,包括DOM的Document对象、Node对象等。同时,对比了DOM与dom4j的优缺点,指出DOM在处理大型文档时的资源消耗问题,而dom4j则以其易用性和性能受到青睐。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、XML

简单介绍一下xml文件。
可扩展标记语言,标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言。

什么是可扩展标记语言

  • 可扩展标记语言是一种很像超文本标记语言的标记语言。
  • 它的设计宗旨是传输数据,而不是显示数据。
  • 它的标签没有被预定义。您需要自行定义标签。
  • 它被设计为具有自我描述性。
  • 它是W3C的推荐标准。

    很多人可能会想到HTML超文本标记语言。

可扩展标记语言和超文本标记语言之间的差异

  • 可扩展标记语言不是超文本标记语言的替代。
  • 可扩展标记语言是对超文本标记语言的补充。
  • 超文本标记语言旨在显示信息,而可扩展标记语言旨在传输信息。
  • 可扩展标记语言是独立于软件和硬件的信息传输工具。

2、解析xml文件

这里简单介绍一些DOM的基本对象。
Document,Node,NodeList,Element和Attr。

  • Document 对象是一棵文档树的根,可为我们提供对文档数据的最初(或最顶层)的访问入口。
  • Node对象是DOM结构中最为基本的对象,代表了文档树中的一个抽象的节点。
  • NodeList对象是是代表了一个包含了一个或者多个Node的列表。可以简单的把它看成一个Node的数组
  • Element对象是XML文档中的标签元素,继承于Node,亦是Node的最主要的子对象。在标签中可以包含有属性,因而Element对象中有存取其属性的方法,而任何Node中定义的方法,也可以用在Element对象上面。
  • Attr 对象表示 Element 对象的属性。属性的容许值通常定义在 DTD 中。
    由于 Attr 对象也是一种节点,因此它继承 Node 对象的属性和方法。不过属性无法拥有父节点,同时属性也不被认为是元素的子节点,对于许多 Node 对象的属性来说都将返回 null。

2.1 DOM解析xml文件

第一步:创建一个xml文件。

<?xml version="1.0" encoding="GBK"?>

<exam> 
  <student examid="222" idcard="324"> 
    <name>李四</name>  
    <location>上海</location>  
    <grade>70</grade> 
  </student>  
  <student examid="333" idcard="999"> 
    <name>王五</name>  
    <location>武汉</location>  
    <grade>40</grade> 
  </student>
</exam>

第二步:生成对应的JavaBean。
(忽略命名不规范,捂脸wu)

class Student {
    private String name;
    private String examid;
    private String idcard;
    private String location;
    private String grade;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getExamid() {
        return examid;
    }

    public void setExamid(String examid) {
        this.examid = examid;
    }

    public String getIdcard() {
        return idcard;
    }

    public void setIdcard(String idcard) {
        this.idcard = idcard;
    }

    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }

    public String getGrade() {
        return grade;
    }

    public void setGrade(String grade) {
        this.grade = grade;
    }
}

第三步:获取xml文件的Document对象

private static Document getDocument() throws ParserConfigurationException,
            SAXException, IOException {
        //得到创建DOM解析器工厂
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        //得到DOM解析器对象
        DocumentBuilder builder = factory.newDocumentBuilder();
        //得到代表整个文档的Document对象
        Document document = builder.parse(new File("test.xml"));
        return document;
    }

第四步:基础的增、删、查操作

private static void query(String name) throws Exception {
        Document document = getDocument();
        NodeList list = document.getElementsByTagName("student");
        for(int i = 0; i < list.getLength(); i++) {
            Element element = (Element) list.item(i);
            String value = element.getElementsByTagName("name").item(0).getTextContent();
            if(name.equals(value)) {
                System.out.println("学生姓名:" +
                  element.getElementsByTagName("name").item(0).getTextContent());
                System.out.println("学生出生地:" +
                        element.getElementsByTagName("location").item(0).getTextContent());
                System.out.println("学生成绩:" +
                        element.getElementsByTagName("grade").item(0).getTextContent());
                System.out.println("学号:" +
                        element.getAttribute("idcard"));
                System.out.println("考号:" +
                        element.getAttribute("examid"));
            }
        }
    }

    private static void delete(String name) throws Exception {
        Document document = getDocument();
        NodeList nodeList = document.getElementsByTagName("name");
        for(int i = 0; i < nodeList.getLength(); i++) {
            Node node = nodeList.item(i);
            if(node.getTextContent().equals(name)) {
                node.getParentNode().getParentNode().removeChild(node.getParentNode());
            }
        }
        write(document);
    }

    private static void add(Student student) throws Exception {
        Document document = getDocument();
        Element studentNode = document.createElement("student");
        studentNode.setAttribute("idcard", student.getIdcard());
        studentNode.setAttribute("examid", student.getExamid());

        Node name = document.createElement("name");
        name.setTextContent(student.getName());
        Node location = document.createElement("location");
        location.setTextContent(student.getLocation());
        Node grade = document.createElement("grade");
        grade.setTextContent(student.getGrade());

        studentNode.appendChild(name);
        studentNode.appendChild(location);
        studentNode.appendChild(grade);

        Element root = document.getDocumentElement();
        root.appendChild(studentNode);

        write(document);
    }

为什么没有改操作啊,因为我忘记写了啊emmm。

第五步:将数据写回xml文件

private static void write(Document document) throws TransformerException {
        DOMSource source = new DOMSource(document);
        StreamResult rs = new StreamResult(new File("test.xml"));
        TransformerFactory factory = TransformerFactory.newInstance();
        Transformer transformer = factory.newTransformer();
        transformer.transform(source, rs);
    }

基础的解析操作差不多完成,下面是main函数。

public static void main(String[] args) throws Exception {
        System.out.println("a:添加学生信息");
        System.out.println("b:删除学生信息");
        System.out.println("c:查询学生信息");
        System.out.print("请选择操作类型:");
        String type;
        Scanner in = new Scanner(System.in);
        type = in.nextLine();
        switch (type) {
            case "a":
                Student student = CreateStudent();
                add(student);
                break;
            case "b":
                System.out.print("请输入删除的学生姓名:");
                String name = in.nextLine();
                delete(name);
                break;
            case "c":
                System.out.print("请输入学生的姓名:");
                name = in.nextLine();
                query(name);
                break;
            default:
                break;
        }
    }

2.2用dom4j解析xml

第一步:导包
这里写图片描述
dom4j包下载
jaxen包下载

第二步:获取Document对象
选取对象导包的时候,不要导入错误。

private static org.dom4j.Document getDocument() throws Exception {
        SAXReader saxReader = new SAXReader();
        FileInputStream in = new FileInputStream(new File("test.xml"));
        Reader reader = new InputStreamReader(in, "GBK");
        org.dom4j.Document document = saxReader.read(reader);

        return document;
    }

这里就有一点奇怪,虽然在将数据写入xml文件时,设置编码格式为GBK,打开文件发现,其编码还是ASCII,所以读取文件的时候,需要将编码格式设置为GBK,负责读取出来的中文会乱码。

第三步:基础操作

    //DOM4j解析方式
    private static void query(String name) throws Exception {
        org.dom4j.Document document = getDocument();

//        List<org.dom4j.Node> element =  document.selectNodes("//student");
//
//        for(int i = 0; i < element.size(); i++) {
//            org.dom4j.Node node = element.get(i);
//            System.out.println(node.toString());
//            System.out.println(node.selectSingleNode("//name").getText());
//            if(node.selectSingleNode("//name").getText().equals(name)) {
//                System.out.println("学生姓名:" + node.selectSingleNode("//name").getText());
//                System.out.println("学生出生地:" + node.selectSingleNode("//location").getText());
//                System.out.println("学生成绩:" + node.selectSingleNode("//grade").getText());
//
//            }
//        }

        List<org.dom4j.Node> element =  document.selectNodes("//student/name");

        for(int i = 0; i < element.size(); i++) {
            org.dom4j.Node node = element.get(i);
            if(node.getText().equals(name)) {
                System.out.println("学生姓名:" + node.getParent().element("name").getText());
                System.out.println("学生出生地:" + node.getParent().element("location").getText());
                System.out.println("学生成绩:" + node.getParent().element("grade").getText());

            }
        }
    }

    private static void delete(String name) throws Exception {
        org.dom4j.Document document = getDocument();
        List<org.dom4j.Node> nodes = document.selectNodes("//name");

        for(int i = 0; i < nodes.size(); i++) {
            org.dom4j.Node node = nodes.get(i);
            if(node.getText().equals(name)) {
                node.getParent().getParent().remove(node.getParent());
            }
        }

        write(document);
    }

    private static void add(Student student) throws Exception{
        try {
            org.dom4j.Document document = getDocument();
            org.dom4j.Element rootElement = document.getRootElement();

            org.dom4j.Element element = rootElement.addElement("student");
            element.addAttribute("examid","123");
            element.addAttribute("idcard", "456");

            element.addElement("name").setText(student.getName());
            element.addElement("location").setText(student.getLocation());
            element.addElement("grade").setText(student.getGrade());

            write(document);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void write(org.dom4j.Document document) throws Exception {
        //设置编码格式
        OutputFormat format = OutputFormat.createPrettyPrint();
        format.setEncoding("GBK");
        XMLWriter writer = new XMLWriter(new FileWriter("test.xml"), format);
        writer.write(document);
        writer.close();
    }

    private static org.dom4j.Document getDocument() throws Exception {
        SAXReader saxReader = new SAXReader();
        FileInputStream in = new FileInputStream(new File("test.xml"));
        Reader reader = new InputStreamReader(in, "GBK");
        org.dom4j.Document document = saxReader.read(reader);

        return document;
    }

感兴趣的朋友,可以试试我注释的那段代码进行查找,可以体会到,我是怎么被selectSingleNode()函数,玩死去活来的。想不明白,有点蛋疼。
我只是觉得这个函数的输出跟我想象的很不一样,贼不一样,很烦。

第四步:将数据写会xml文件

    private static void write(org.dom4j.Document document) throws Exception {
        //设置编码格式
        OutputFormat format = OutputFormat.createPrettyPrint();
        format.setEncoding("GBK");
        XMLWriter writer = new XMLWriter(new FileWriter("test.xml"), format);
        writer.write(document);
        writer.close();
    }

3、DOM方法与dom4j比较

3.1 DOM

DOM 是用与平台和语言无关的方式表示 XML 文档的官方 W3C 标准。DOM 是以层次结构组织的节点或信息片断的集合。这个层次结构允许开发人员在树中寻找特定信息。分析该结构通常需要加载整个文档和构造层次结构,然后才能做任何工作。
使用DOM特别注意的一点就是:对于特别大的文档,解析和加载整个文档可能很慢且很耗资源,因此使用其他手段来处理这样的数据会更好。

3.2 dom4j

DOM4J 代表了完全独立的开发结果,但最初,它是 JDOM 的一种智能分支。它合并了许多超出基本 XML 文档表示的功能,包括集成的 XPath 支持、XML Schema 支持以及用于大文档或流化文档的基于事件的处理。它还提供了构建文档表示的选项,它通过 DOM4J API 和标准 DOM 接口具有并行访问功能。
DOM4J 是一个非常非常优秀的Java XML API,具有性能优异、功能强大和极端易用使用的特点,同时它也是一个开放源代码的软件。如今你可以看到越来越多的 Java 软件都在使用 DOM4J 来读写 XML,特别值得一提的是连 Sun 的 JAXM 也在用 DOM4J。

个人而言,我更喜欢dom4j一点。

附: jaxen包的导入是为了支持XPath,就是在方法中的 //student/name这样的,具体的我也说不清楚,情况很多,大家自行百度哈。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值