XML解析

1 概念

xml:extended markup language  :可扩展的标记语言
语法:标记类语言的语法:<标签名  属性名="属性值" 属性名="属性值">数据</标签名>
  • xml和html的区别
概念:xml html
相同之处:都是标记类语言:语法相同  作用都是通过标签封装数据
不同之处:
      1: html的标签和属性是预定义的:
       xml的标签和属性是自定义 
       
     2: 是否区分大小写
       
  • 解析
浏览器内置有对标记类语言解析的引擎

注意事项

* 纯文本语言:后缀名必须是.xml
* xml文件必须有两部分组成:声明区+数据区
* 数据区有且只有一个根标签:所有的其他标签都是此根标签的子标签
* 标签之前可以合理嵌套
* 属性写在起始标签中:属性格式:属性名=属性值
* 属性值可以写在单引号、双引号、不加引号:规范:双引号
* 标签名/属性名:命名规范:由数字 字母 _ 汉字等组成  但不能以数字开头
* 标签名/属性名区分大小写
* 通过字符实体来表示特殊字符
  • student.xml
<?xml version='1.0' encoding='utf-8' ?>  <!--声明区:设置当前xml的版本和编码集-->
<!--数据区:当前xml中的数据-->
<dangAn  id="10001">
       <班级 id="cla_1">
            <student id="stu_11">
                   <sname>韩梅梅</sname>
                   <sex>女</sex>
                   <score>11.5</score>
                   <sdy>false</sdy>
            </student>
            <student id="stu_12">
                   <sname>韩庚</sname>
                   <sex>男</sex>
                   <score>21.5</score>
                   <sdy>true</sdy>
            </student>  
            <student id="stu_13">
                   <sname>韩信</sname>
                   <sex>男</sex>
                   <score>41.5</score>
                   <sdy>false</sdy>
            </student>  
       </班级>
       <班级 id="cla_2">
            <student id="stu_21">
                   <sname>张三</sname>
                   <sex>女</sex>
                   <score>12.5</score>
                   <sdy>false</sdy>
            </student>
            <student id="stu_22">
                   <sname>张三丰</sname>
                   <sex>男</sex>
                   <score>22.5</score>
                   <sdy>true</sdy>
            </student>  
            <student id="stu_23">
                   <sname>张国荣</sname>
                   <sex>男</sex>
                   <score>42.5</score>
                   <sdy>false</sdy>
            </student>
             <student id="stu_23">
                   <sname>&lt; a &gt;</sname>
                   <sex>男</sex>
                   <score>52.5</score>
                   <sdy>false</sdy>
            </student>  
        </班级>
</dangAn>

作用

作为软件的配置文件:配置信息:软件启动或者运行中需要加载的数据
                 封装有关系的数据

2 xml解析

https://blog.csdn.net/cui__shen/article/details/90813385

方法

  • DOM解析
dom:document object model 文档对象模型
    原理:把xml文档和文档中的所有元素封装为对象  这些有关系的对象 写成dom树
w3c的规范    
  • SAX解析
sax:smple api for xml
    原理:以事件驱动的机制 对xml文档进行快速扫描
         只支持快速读取  不支持对文档的增删改
  • dom4j
对dom的封装,简化
  • jdom

dom和sax的不同

概念:
不同之处:
     1 dom支持对xml的增删改查
       sax只支持读取 不支持增删改
     2 dom需要把文档和元素都封装为对象  非常消耗内存  不建议读取大文件
       sax擅长读取大文件

3 dom解析

把xml文档和文档中的所有元素封装为对象  这些有关系的对象 写成dom树

相关的类型

包:org.w3c.dom 
-- Node接口: 所有类型的根接口-- 节点(元素)
---- Element接口:所有的标签
---- Text接口:   所有的文本
---- Comment接口:  所有的注释
---- Attr接口:     所有的属性
---- Document接口: 文档本身

3.0 准备

public static void main(String[] args) {
    //获取xml
    File file=new File("src\\1.txt");
    System.out.println(file.getAbsolutePath());
    //获取xml
    String path=Test01.class.getClassLoader().getResource("dangAn.xml").getPath();
    System.out.println(path);

    //获取document对象
    Document doc=xml2Doc(path);
    System.out.println(doc);

}
//由xml获取document对象
public static Document xml2Doc(String path){
    try {
        //获取文档解析器工厂对象
        DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
        //获取文档解析器对象
        DocumentBuilder  builder=factory.newDocumentBuilder();//实例工厂模式:
        //通过解析器对象的parse 由xml获document对象
        return builder.parse(new File(path));
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}
//吧document对象刷新到xml中
public static void  doc2Xml(String path,Document doc){
    try {
        //创建Transformer工厂对象
        TransformerFactory factory=TransformerFactory.newInstance();
        //创建Transformer对象
        Transformer tf=factory.newTransformer();
        //设置编码集合:默认utf-8
        tf.setOutputProperty(OutputKeys.ENCODING, "GBK");
        //调用taranform方法把doc的信息刷新到xml中
        tf.transform(new DOMSource(doc), new StreamResult(new File(path)));
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

3.1 查询

  • 相关方法
	 * Document的方法:
	 *       NodeList getElementsByTagName(标签名);获取文档中指定的所有标签对应的集合
	 * Element的方法:
	 *       NodeList getElementsByTagName(标签名);获取当前标签对象中指定的子标签对应的集合
	 *       String  getTextContent();获取文本内容
	 *       NamedNodeMap getAttributes();获取所有的属性
	 * Node的方法:
	 *       String getNodeName(); 获取元素名字
	 *       int  getNodeType() ; 获取元素的类型:Document是9    Comment是8 Element是1 Attr是2 Text是3
	 *       NodeList getChildNodes(); 获取所有的子元素::标签+文本
	 *       Boolean  hasChildNodes(); 判断是否有子元素
	 * Attr的方法
	 *       String  getName();获取属性名
	 *       String  getValue();获取属性值
	 * NamedNodeMap和 NodeList的方法
	 *      int getLength()  
	 *	    Node item(int index)
  • 代码
//遍历整个xml文件
public static void showDoc(Node node){
    System.out.println("元素:"+node.getNodeName()+":"+node.getNodeType());
    //判断类型
    if(node instanceof Document){
        System.out.println("当前元素是:文档");
        //获取其所有的子标签
        NodeList zis=node.getChildNodes();
        if(zis!=null){
            for (int i = 0; i < zis.getLength(); i++) {
                Node zi=zis.item(i);
                showDoc(zi);
            }
        }
    }else if(node instanceof Element){
        Element ele=(Element)node;
        System.out.println("当前元素是:标签");
        //获取属性
        NamedNodeMap attrs= ele.getAttributes();
        if(attrs!=null){
            for (int i = 0; i < attrs.getLength(); i++) {
                showDoc(attrs.item(i));
            }
        }
        //判断是否有子标签
        if(ele.hasChildNodes()){
            NodeList zis=ele.getChildNodes();
            for (int i = 0; i < zis.getLength(); i++) {
                showDoc(zis.item(i));
            }
        }else{
            //获取文本内容
            System.out.println("当前标签的文本内容:"+ele.getTextContent());
        }
    }else if(node instanceof Attr){
        Attr attr=(Attr) node;
        System.out.println("属性:"+attr.getName()+"="+attr.getValue());
    }else if(node instanceof Comment ){
        Comment com=(Comment)node;
        System.out.println("注释:"+com.getNodeValue());
    }

}

3.2 修改

  • 相关方法
	 * Element的方法:
	 *       String getAttribute(String); 获取属性值
	 *       void  setAttribute(String,String); 添加/修改属性值
	 *       void  removeAttribute(String); 删除属性
	 *       
	 *       String  getTextContent();获取文本内容
	 *       void  setTextContent(String);设置文本内容
	 *       
	 *       Node  getParentNode();获取父标签
  • 代码
public static void update2(String path){
    Document doc=xml2Doc(path);
    //吧班级为id=cla_2的名字为张三丰的学生的性别更改为妖
    //获取所有的班级标签
    NodeList  list=doc.getElementsByTagName("班级");
    for (int i = 0; i < list.getLength(); i++) {
        Element eleBanJi=(Element)list.item(i);
        //获取其id属性
        String id=eleBanJi.getAttribute("id");
        if(id.equals("cla_2")){
            System.out.println("1111");
            //获取其中所有的sname标签
            NodeList snameList=eleBanJi.getElementsByTagName("sname");
            for (int j = 0; j < snameList.getLength(); j++) {
                //获取cla_2下的一个sname标签
                Element eleSname=(Element)snameList.item(j);
                //获取其文本内容
                String sname=eleSname.getTextContent().trim();
                if(sname.equals("张三丰")){
                    //获取当前sname标签的父标签student标签
                    Element eleStu=(Element)eleSname.getParentNode();
                    //获取此父亲标签的sex子标签
                    Element eleSex=(Element)eleStu.getElementsByTagName("sex").item(0);
                    //修改完毕内容
                    eleSex.setTextContent("仙");
                    //添加学生标签的属性值
                    eleStu.setAttribute("title", "t9999");
                    //更改学生标签的属性
                    eleStu.setAttribute("id", "s_00001");
                    break;
                }

            }
            break;
        }
    }
    //吧更改后的document对象的信息刷新到xml中
    doc2Xml(path,doc);
}

3.3 添加

  • 相关方法
	 * Document的方法:
	 *       Node createElement(String);创建一个标签
	 * Element的方法:            
	 *       Node appendChild(node); 在当前标签下添加一个子标签  返回值是子标签
  • 代码
public static void add(Student s,String path){
    //把参数student对象的信息添加到第一个班级标签下
    Document doc=xml2Doc(path);
    //获取第一个班级标签
    Element eleBJ=(Element)doc.getElementsByTagName("班级").item(0);
    //创建student标签
    Element eleStu=(Element)doc.createElement("student");
    //添加id属性
    eleStu.setAttribute("id", s.getId());
    //创建子标签
    Element eleSname=(Element)doc.createElement("sname");
    Element eleSex=(Element)doc.createElement("sex");
    Element eleScore=(Element)doc.createElement("score");
    Element eleSdy=(Element)doc.createElement("sdy");
    //设置文本内容
    eleSname.setTextContent(s.getSname());
    eleSex.setTextContent(s.getSex()+"");
    eleScore.setTextContent(s.getScore()+"");
    eleSdy.setTextContent(s.getSdy()+"");
    //把子标签添加到父标签下
    eleStu.appendChild(eleSname);
    eleStu.appendChild(eleSex);
    eleStu.appendChild(eleScore);
    eleStu.appendChild(eleSdy);
    System.out.println(eleBJ.appendChild(eleStu).getNodeName());
    //吧更改后的document对象的信息刷新到xml中
    doc2Xml(path,doc);
}

3.4 删除

  • 相关方法
     * Element的方法:            
	 *       void removeChild(node);删除当前标签的参数子标签
	 *       void removeAttribute(String); 删除属性
  • 代码
public static void delete(String path){
    //把参数student对象的信息添加到第一个班级标签下
    Document doc=xml2Doc(path);
    //删除第一个student标签的title属性
    Element eleStu=(Element)doc.getElementsByTagName("student").item(0);
    eleStu.removeAttribute("title");

    //删除第二个student标签
    Element eleStu2=(Element)doc.getElementsByTagName("student").item(1);
    eleStu2.getParentNode().removeChild(eleStu2);//通过父标签 删除子标签

    //吧更改后的document对象的信息刷新到xml中
    doc2Xml(path,doc);
}

4 xml练习

public class Teacher {
	// tid tname tsex tsalary tbirthday
	private int tid;
	private String tname;
	private String tsex;
	private float tsalary;
	private Date tbirthday;
    ...
}
package com.zhiyou100.demo02.xml;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

public class LianXi {
	private static File file;
	static{
		file=new File("src/Teacher.xml");
		init();
	}
	private static void init(){
		if(!file.exists()){
			try {
				file.createNewFile();
				//添加声明区和根标签 dangAn
				BufferedWriter  bout=new BufferedWriter(new FileWriter(file));
				bout.write("<?xml version=\"1.0\" encoding=\"gbk\" standalone=\"no\"?>");
				bout.newLine();
				bout.write("<dangAn>");
				bout.newLine();
				bout.write("</dangAn>");
				bout.flush();
				bout.close();
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
	}
	public static void main(String[] args) {
              //添加
//		      addOne(new Teacher(1002, "张三丰", "男", 3050, new Date(0)));
//		      addOne(new Teacher(1003, "张无忌", "男", 3100, new Date(0)));
//		      addOne(new Teacher(1004, "张翠山", "男", 3200, new Date(0)));
//		      addOne(new Teacher(1005, "张思", "女", 3030, new Date(0)));
//		      addOne(new Teacher(1006, "刘思思", "女", 3400, new Date(0)));
		//System.out.println(deleteOne(1001));
		//System.out.println(deleteOne(1001));
		
		//updateOne(new Teacher(1006, "刘sisi", "妖", 3333, new Date(0)));
		
		List<Teacher> list=getAll();
		for (Teacher teacher : list) {
			System.out.println(teacher);
		}
	}
	//添加一个:把一个老师对象的信息添加到xml中 对应一个teacher标签
	//  void addOne(Teacher t);
	public static void addOne(Teacher  t){
		//int tid, String tname, String tsex, float tsalary, Date tbirthday
		Document doc=xml2Doc(file);
		//获取dangAn标签
		Element root=(Element)doc.getElementsByTagName("dangAn").item(0);
		//创建teacher标签
		Element eleTea=doc.createElement("Teacher");
		//添加属性
		eleTea.setAttribute("tid", t.getTid()+"");
		//创建子标签
		Element eleTname=doc.createElement("tname");
		eleTname.setTextContent(t.getTname());
		Element eleTsex=doc.createElement("tsex");
		eleTsex.setTextContent(t.getTsex());
		Element eleTsalary=doc.createElement("tsalary");
		eleTsalary.setTextContent(t.getTsalary()+"");
		Element eleTbirthday=doc.createElement("tbirthday");
		eleTbirthday.setTextContent(t.getTbirthday().toLocaleString());
		//把子标签添加到父标签上
		root.appendChild(eleTea);
		eleTea.appendChild(eleTname);
		eleTea.appendChild(eleTsex);
		eleTea.appendChild(eleTsalary);
		eleTea.appendChild(eleTbirthday);
		//把doc刷新到xml中
		doc2Xml(file, doc);
	}
	//删除一个:根据 
	//  int deleteOne(int tid);
	public static int deleteOne(int id){
		//int tid, String tname, String tsex, float tsalary, Date tbirthday
		Document doc=xml2Doc(file);
		//获取dangAn标签
		NodeList teaList=doc.getElementsByTagName("Teacher");
		boolean b=false;
		for (int i = 0; i < teaList.getLength(); i++) {
			Element eleTea=(Element)teaList.item(i);
			//获取其tid属性
			int tid=Integer.parseInt(eleTea.getAttribute("tid"));
			if(tid==id){
				 eleTea.getParentNode().removeChild(eleTea);
				 b=true;
				 break;
			}
		}
		//把doc刷新到xml中
		doc2Xml(file, doc);
		return b?1:0;
	}
	//修改一个
	// int updateOne(Teacher t);
	public static int updateOne(Teacher  t){
		//int tid, String tname, String tsex, float tsalary, Date tbirthday
		Document doc=xml2Doc(file);
		//获取dangAn标签
		NodeList teaList=doc.getElementsByTagName("Teacher");
		boolean b=false;
		for (int i = 0; i < teaList.getLength(); i++) {
			Element eleTea=(Element)teaList.item(i);
			//获取其tid属性
			int tid=Integer.parseInt(eleTea.getAttribute("tid"));
			if(tid==t.getTid()){
				 //更改子标签的文本内容
				 eleTea.getElementsByTagName("tname").item(0).setTextContent(t.getTname());
				 eleTea.getElementsByTagName("tsex").item(0).setTextContent(t.getTsex());
				 eleTea.getElementsByTagName("tsalary").item(0).setTextContent(t.getTsalary()+"");
				 eleTea.getElementsByTagName("tbirthday").item(0).setTextContent(t.getTbirthday().toLocaleString());
				 b=true;
				 break;
			}
		}
		//把doc刷新到xml中
		doc2Xml(file, doc);
		return b?1:0;
	}
	//获取所有
	// List<Teacher> getAll();
	public static List<Teacher> getAll(){
		//int tid, String tname, String tsex, float tsalary, Date tbirthday
		Document doc=xml2Doc(file);
		//获取dangAn标签
		NodeList teaList=doc.getElementsByTagName("Teacher");
		List<Teacher> list=new ArrayList<Teacher>();
		for (int i = 0; i < teaList.getLength(); i++) {
			 Element eleTea=(Element)teaList.item(i);
			 Teacher t=new Teacher();
			 t.setTid(Integer.parseInt(eleTea.getAttribute("tid")));
			 t.setTname(eleTea.getElementsByTagName("tname").item(0).getTextContent());
			 t.setTsex(eleTea.getElementsByTagName("tsex").item(0).getTextContent());
			 t.setTsalary(Float.parseFloat(eleTea.getElementsByTagName("tsalary").item(0).getTextContent()));
			 String tbirthdayStr=eleTea.getElementsByTagName("tbirthday").item(0).getTextContent();
			 try {
				 //1970-1-1 8:00:00
				 t.setTbirthday(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(tbirthdayStr));
			} catch (Exception e) {
				throw new RuntimeException(e);
			}
			 list.add(t);
		}
		return list;
		
	}
	// 由xml获取document对象
	public static Document xml2Doc(File file) {
		try {
			// 获取文档解析器工厂对象
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			// 获取文档解析器对象
			DocumentBuilder builder = factory.newDocumentBuilder();// 实例工厂模式:
			// 通过解析器对象的parse 由xml获document对象
			return builder.parse(file);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	// 吧document对象刷新到xml中
	public static void doc2Xml(File file, Document doc) {
		try {
			// 创建Transformer工厂对象
			TransformerFactory factory = TransformerFactory.newInstance();
			// 创建Transformer对象
			Transformer tf = factory.newTransformer();
			// 设置编码集合:默认utf-8
			tf.setOutputProperty(OutputKeys.ENCODING, "GBK");
			// 调用taranform方法把doc的信息刷新到xml中
			tf.transform(new DOMSource(doc), new StreamResult(file));
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
}

posted @ 2021-10-30 22:17  RenVei  阅读(28)  评论(0编辑  收藏  举报