一,XML是什么?

XML:Extensible Markup Language 可扩展标记语言
XML可以将数据与HTML的格式分离.
比如要在HTML中显示动态的数据,那么每当数据改变时,都需要花费时间来编辑HTML中的各种标签元素什么的,
通过XML文件,数据能够存储在独立的XML文件中,这样可以保证,当修改底层数据时,不再需要对HTML文件做任何更改.
而外部的XML文件,也可以通过JS来读取,然后更新HTML中的数据内容.
不同的计算机系统,不同的应用程序,不同的客户端等,存储信息的格式很可能是不同的,而XML数据,是以纯文本的格式进行存储的,
所以可以通过XML数据来在不同的环境中共享数据(像不像JavaScript Object Notation).
所以说XML数据,提供了一种独立于软件和硬件的数据存储方式.

二,XML中的节点

Node对象,就是XML文件中的节点,XML文件中的节点有很多,常用的有三种,元素(标签),属性(标签中的属性),文本(开始结束标签中的文本内容)

需要注意的是:XML文件不像HTML文件那样会忽略空白字符,XML中是识别空格,制表符,换行符等空白字符的.


java解析xml重复标签 jaxb java解析xml文件的标签内容_xml



java解析xml重复标签 jaxb java解析xml文件的标签内容_java解析xml重复标签 jaxb_02

与src文件平级,建立一个test.xml文件,文件内容如下.

<?xml version="1.0" encoding="UTF-8"?>
<students>
  <student id="1">
    <name>张三</name>
    <score>30</score>
    <like>basketball</like>
    <goodat>dance</goodat>
  </student>

  <student id="2">
    <name>李四</name>
    <score>40</score>
    <like>lol</like>
    <goodat>song</goodat>
  </student>
</students>

java解析xml重复标签 jaxb java解析xml文件的标签内容_解析_03

三,DOM解析

DOM解析,会将XML文件中的所有内容,一次性加载进内存中解析.


java解析xml重复标签 jaxb java解析xml文件的标签内容_数据_04

先获取XML文件中的数据

//要解析xml中的数据,需要先获得内容,就相当于网络拉取的过程
//第一步创建一个DocumentBuilderFactory的对象
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
    //第二步创建一个DocumentBuilder的对象
    DocumentBuilder documentBuilder = dbf.newDocumentBuilder();
    //第三步:(可以传入绝对路径也可以传入相对路径)
    //通过parse方法加载test.xml文件到当前目录下(这样就将文件中的数据信息加载到document对象上了)
    //得到document对象,注意是:org.w3c包下的
    org.w3c.dom.Document document = documentBuilder.parse("test.xml");
} catch (ParserConfigurationException e) {
    e.printStackTrace();
}

获得所有的student节点

//下面是解析的步骤
//第一步,通过标签名获得标签(是所有student节点的集合)
NodeList studentList = document.getElementsByTagName("student");
//test.xml文件中,有两个student标签,这里获得的集合中输出的length也就是2
System.out.println("一共有:  " + studentList.getLength());

获得student节点的属性

1,已知节点的属性(比如这里知道节点的属性为id)

for (int i = 0;i<studentList.getLength() ;i++ ) {
  //获取集合中第i位置的元素
  Element element = (Element)studentList.item(i);
  //通过属性名获取该元素的属性值
  String id = element.getAttribute("id");
}

2,不知道节点的属性有多少值都是什么

//获取属性名属性值,遍历每一个student节点
for (int i = 0; i < studentList.getLength(); i++) {
  //通过 item(i)方法 获取一个student的节点信息(索引都是从零开始的)
  //Node类的对象,就表示一个节点对象,含有该节点的信息
  Node student = studentList.item(i);
  //获得student这个节点的所有属性的集合
  NamedNodeMap attrs = student.getAttributes();
  for (int j = 0; j < attrs.getLength(); j++) {
    Node attr = attrs.item(j);//获取属性
    System.out.printf(attr.getNodeName());//获得属性名称
    System.out.println(attr.getNodeValue());//获得属性值
  }
}

获得student节点的子节点

student节点的子节点有:文本,name元素,文本,score,文本,like,文本,goodat,文本
所以student一共有9个子节点,下面获得节点name和value并打印出来

NodeList nodeList = student.getChildNodes();
System.out.println("第"+(i + 1)+"个student节点的子节点数量:"+nodeList.getLength());
//发现输出的结果是9
//是因为在<name>节点的前后,有空格与换行符存在,前后两个,就是两个文本节点
//文本节点+name节点+文本节点=9
for (int j = 0; j < nodeList.getLength(); j++) {
  //获取每一个子节点对象
  Node node = nodeList.item(j);

  //输出每个子节点的属性与属性值
  System.out.println("第"+(j+1)+"个节点名为:"+node.getNodeName()+"---值为:"+node.getNodeValue()+"---");

  //所以能看到控制台输出时,当属性为#text时,值是空格加换行符
  //文本的节点名为:#text
  //元素的节点名:就是尖括号中的元素名
  //元素的nodeValue值就是开始标签与结束标签中间的文本内容
}

java解析xml重复标签 jaxb java解析xml文件的标签内容_数据_05


java解析xml重复标签 jaxb java解析xml文件的标签内容_java_06

同样的方式可以再获得子节点的子节点

下面是DOM解析的完整代码

public class ResolveXMLDemo {
  private static List<Student> data ;
  public static void main(String[] args) {
    blogDocumentDemo();
    showData();
  }

  private static void showData() {
    for (int i = 0; i < data.size(); i++) {
      Student student = data.get(i);
      System.out.println("student---id:"+student.getId()+"--name:"+student.getName());
    }
  }

  private static void blogDocumentDemo() {
    data = new ArrayList<>();
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    try {
      //第二步创建一个DocumentBuilder的对象
      DocumentBuilder documentBuilder = dbf.newDocumentBuilder();
      //第三步:(可以传入绝对路径也可以传入相对路径)
      //通过parse方法加载test.xml文件到当前目录下(这样就将文件中的数据信息加载到document对象上了)
      //得到document对象,注意是:org.w3c包下的
      org.w3c.dom.Document document = documentBuilder.parse("test.xml");

      //下面是解析的步骤
      //第一步,通过标签名获得标签(是所有student节点的集合)
      NodeList studentList = document.getElementsByTagName("student");

      //第二步,获取属性名属性值,遍历每一个student节点
      for (int i = 0; i < studentList.getLength(); i++) {

        //通过 item(i)方法 获取一个student的节点信息(索引都是从零开始的)
        Node student = studentList.item(i);
        Student studentEntity = new Student();

        //遍历student节点中的属性
        //先拿到student节点的所有属性的集合
        NamedNodeMap attrs = student.getAttributes();
        for (int j = 0; j < attrs.getLength(); j++) {
          Node attr = attrs.item(j);//获得第j个属性
          if(attr.getNodeName().equals("id")){
              studentEntity.setId(attr.getNodeValue());
          }
        }

        //获取student节点的子节点的内容
        for (int j = 0; j < student.getChildNodes().getLength(); j++) {
          //获取每一个子节点对象
          Node node = student.getChildNodes().item(j);
          //输出每个子节点的属性与属性值
          String nodeName = node.getNodeName();
          String nodeValue = node.getNodeValue();
          switch (nodeName){
            case "name":
                studentEntity.setName(nodeValue);
                break;
            case "score":
                studentEntity.setScore(nodeValue);
                break;
            case "like":
                studentEntity.setLike(nodeValue);
                break;
            case "goodat":
                studentEntity.setGoodAt(nodeValue);
                break;
          }
        }
        data.add(studentEntity);
      }

    } catch (ParserConfigurationException e) {
      e.printStackTrace();
    } catch (SAXException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}