XML解析

xml的解析的简介
    xml是标记型文档
    使用dom解析标记型文档?
        - 根据html的层级结构,在内存中分配一个树形结构,把html的标签,属性和文本都封装成对象
        - document对象、element对象、属性对象、文本对象、Node节点对象
    
    xml的解析方式(技术):dom 和 sax
        画图分析使用dom和sax解析xml过程
        dom解析和sax解析区别:
        dom方式解析
            根据xml的层级结构在内存中分配一个树形结构,把xml的标签,属性和文本都封装成对象
            缺点:如果文件过大,造成内存溢出
            优点:很方便实现增删改操作

        sax方式解析
            采用事件驱动,边读边解析
                - 从上到下,一行一行的解析,解析到某一个对象,返回对象名称
            缺点:不能实现增删改操作
            优点:如果文件过大,不会造成内存溢出,方便实现查询操作
    
    想要解析xml,首先需要解析器
        不同的公司和组织提供了 针对dom和sax方式的解析器,通过api方式提供
        sun公司提供了针对dom和sax解析器  jaxp
        dom4j组织,针对dom和sax解析器    dom4j(*** 实际开发中****)
        apache tomcat / lucence
        jdom组织,针对dom和sax解析器     jdom

    获取文档对象Document
        1:SAXReader sax = new SAXReader();
        2:Document doc = sax.read(new fileInputStream("a.xml"));
    首先获取根节点 getRootElemen() -> Element 
    获取根节点下面所有的子节点 elements()
    根据名称获取根节点下面所有的子节点 elements(String name)
    获取根节点下面单个节点 element()
    根据名称获取指定节点 element(String name)
    根据子节点名称获取子节点文本 elementText(String name)
    获取当前节点的文本 getText() -> String;
    设置当前节点的文本 setText(String txt);
    给当前文档对象添加新节点 addElement(String name) -> element.setText(String txt)
    获取父节点 getParent() -> Element parent.remove(Element son) 

    获取某个属性的值:attributeValue(String name)-> String value
    添加或者修改属性的值:addAttribute(String name,String value)
    
    DocumentHelper.createElement(String name) -> element.setText(String txt);

    对文档对象进行添加/删除/修改操作之后 要重新写回到xml中
    1:OutputFormat format = OutputFormat.createPrettyPrint();
    2:XMLWriter xw = new XMLWriter(new fileOutputStream("a.xml"),format);
    3:xw.write(Document doc);
    4;xw.close()

XML解析简单Demo

import java.io.IOException;
import java.util.Iterator;
import java.util.List;

import org.dom4j.Branch;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Node;

/*
 * XML
 * <元素/标签>
 * <City>三门峡</City>
 * 元素/标签 = City    文本  = 三门峡
 * <City Name="河南"/City> 
 * 元素/标签 = City    
 * 属性名:Name
 * 属性值:河南
 * 
 * Dom4J的常用方法:
 * 		Document
 * 			 Element getRootElement() :获取根元素对象(根标签)
 * 		public interface Document extends Branch
 * 		public interface Element extends Branch
 * 		public interface Branch extends Node
 * 		public interface Node extends Cloneable
 * 		Element
 * 			 List elements() :获取所有的子元素
 * 			 List elements(String name):根据指定的元素名称来获取相应的所有的子元素
 * 			 Element element(String name):根据指定的元素名称来获取子元素对象,如果元素名称重复,则获取第一个元素 
 * 			 String	elementText(String name) :根据指定的子元素名称,来获取子元素中的文本
 * 			 String	getText() :获取当前元素对象的文本
 * 			 void setText(String text):设置当前元素对象的文本
 * 			 String	attributeValue(String name):根据指定的属性名称获取其对应的值
 * 			 public Element addAttribute(String name,String value):根据指定的属性名称和值进行添加或者修改
 * 			 addElement
 * 		Node
 * 			Element element(String name):根据指定的元素名称来获取子元素对象,如果元素名称重复,则获取第一个元素 
 * 			String elementText(String name) :根据指定的子元素名称,来获取子元素中的文本
 * 			String getName();获取当前元素对象
 * 			String getText();获取当前元素对象的文本
 * 			String	attributeValue(String name):根据指定的属性名称获取其对应的值
 * 			void setText(String text):设置当前元素对象的文本
 * 		
 * 
 * 		DocumentHelper
 * 			static Element	createElement(String name) 
           
 * 			  
 */
public class Dom4JDemo {
	public static void main(String[] args) throws Exception  {
//		method1();
//		method2();
//		method3();
//		method4();
//		method5();
//		method6();
//		method7();
//		method8();
//		methodTest();
	}
	private static void methodTest() throws Exception{
		//获得Document对象
		Document document = Dom4JUtils.getDocument();
		//获取根元素
		Element rootElement = document.getRootElement();
//		System.out.println(rootElement.getName()+":"+rootElement.getText());
//		System.out.println("---------------------");
		//获取根元素下所有子元素
		List<Element> list = rootElement.elements();
		System.out.println("list.get(0)---------.getName()---.getText()---------");
		//当前元素
		System.out.println(list.get(0).getName()+":"+list.get(0).getText());
		System.out.println("list.get(1)---------.getName()---.getText()---------");
		//当前元素
		System.out.println(list.get(1).getName()+":"+list.get(1).getText());
		System.out.println("list.get(2)---------.getName()---.getText()---------");
		//当前元素
		System.out.println(list.get(2).getName()+":"+list.get(2).getText());
		
		System.out.println("list.get(1)---------elementText------------");
		//子元素的文本
		System.out.println(list.get(1).elementText("Name"));
		//子元素对象:根据指定的元素名称来获取子元素对象
		// Element	element(String name) 
		//Returns the first element for the given local name and any namespace
		Element element = list.get(1).element("Region");
		System.out.println("list.get(1)---------element------------");
		System.out.println(element.getText());
		/*
		String attributeValue(String name) 
        This returns the attribute value for the attribute 
        with the given name and any namespace 
        or null if there is no such attribute 
        or the empty string if the attribute value is empty.
		*/
		System.out.println("list.get(0)--------attributeValue-------------");
		System.out.println(list.get(0).attributeValue("Name"));
		
		//获取根元素下所有子元素
		List<Element>elements = rootElement.elements();
		for(Element e :elements){
			System.out.println("---e.elementText-------------------");
			//子元素:根据指定的子元素名称,来获取子元素中的文本
			System.out.println(e.elementText("Name"));
			System.out.println("---e.getText-------------------");
			//当前元素
			System.out.println(e.getName()+":"+e.getText());
			System.out.println("---------------------");
		}
	}
//	1、得到某个具体的节点内容:打印"郑州"
	private static void method1() throws Exception {
		//获得Document对象
		Document document = Dom4JUtils.getDocument();
		//获取根元素
		Element rootElement = document.getRootElement();
		//获取根元素下所有子元素
		List<Element>elements = rootElement.elements();
		//遍历找到子元素City 打印"郑州"
		for(Element e :elements){
			if (e.getText().equals("襄阳")) {
				System.out.println(e.getText());
				System.out.println(e.elementText("Name"));
				break;
			}
		}
	}
	//2、遍历所有元素节点:打印他们的元素名称。
	private static void method2() throws Exception {
		//获取Document对象
		Document document = Dom4JUtils.getDocument();
		//获取根元素
		Element rootElement = document.getRootElement();
		treeWalk(rootElement);
		myTreeRecur(rootElement);
	}
	//3、修改某个元素节点的主体内容:信阳-->安阳
	private static void method3() throws Exception, IOException {
		//获取Document对象
		Document document = Dom4JUtils.getDocument();
		//获取根元素
		Element rootElement = document.getRootElement();
		//获取所有子节点
		List<Element> elements = rootElement.elements();
		for (Element element : elements) {
			System.out.println(element.getText());
			if(element.getText().equals("南阳")){
				element.setText("洛阳");
			}
		}
		//写回文件
		Dom4JUtils.write2XML(document);
	}
	//6、删除指定元素节点:删除安阳	
	private static void method4() throws Exception, IOException {
		//获取Document对象
		Document document = Dom4JUtils.getDocument();
		//获取根元素
		Element rootElement = document.getRootElement();
		//获取根元素的所有子元素
		List<Element>list = rootElement.elements();
		//遍历集合
		for (int i = 0; i < list.size(); i++) {
			Element e = list.get(i);
			if (e.getText().equals("洛阳")) {
				System.out.println("i-1:"+list.get(i-1).getName()+":"+list.get(i-1).getText());//City:三门峡
				System.out.println("Parent:"+e.getParent().getName());//State
				//list.get(i-1).remove(e);
				//System.out.println("remove洛阳");
			}
			if (e.getText().equals("洛阳")) {
				Element parent = e.getParent();
				parent.remove(e);
				System.out.println("remove洛阳");
			}
		}
		//写回文件
		Dom4JUtils.write2XML(document);
	}
	//4、向指定元素节点中增加子元素节:添加一个新城市<City>南阳</City>
	private static void method5() throws Exception, IOException {
		//获取Document对象
		Document document = Dom4JUtils.getDocument();
		//获取根元素
		Element rootElement = document.getRootElement();
		//添加元素
		Element cityElement = rootElement.addElement("City");
		//设置文本
		cityElement.setText("深圳");
		//写回
		Dom4JUtils.write2XML(document);
	}
	//5、向指定元素节点上增加同级元素节点:在洛阳前面,添加一个<City>香港</City>
	private static void method6() throws Exception, IOException {
		//创建一个新的元素对象
		Element cityElement = DocumentHelper.createElement("City");
		//设置文本
		cityElement.setText("香港");
		//获取Document对象
		Document document = Dom4JUtils.getDocument();
		//获取根元素
		Element rootElement = document.getRootElement();
		//获取子元素集合
		List<Element> list = rootElement.elements();
		//遍历集合
		//错误
//		for (int i = 0;i <list.size();i++) {
//			if(list.get(i).getText().equals("洛阳")){
				System.out.println("i-1:"+list.get(i-1).getName()+":"+list.get(i-1).getText());//City:三门峡
				System.out.println("Parent:"+list.get(i-1).getParent().getName());//State
				System.out.println("i:"+list.get(i).getName()+":"+list.get(i).getText());//City:三门峡
				System.out.println("Parent:"+list.get(i).getParent().getName());//State
//
//				list.add(i,cityElement);
//			}
//		}
		int i = 0;
		for (;i <list.size();i++) {
			if(list.get(i).getText().equals("洛阳")){
				break;
			}
		}
		list.add(i,cityElement);
		
		//写回文件
		Dom4JUtils.write2XML(document);
	}
	//7、操作XML文件属性:打印State的Name
	private static void method7() throws Exception {
		//获取Document对象
		Document document = Dom4JUtils.getDocument();
		//获取根元素
		Element rootElement = document.getRootElement();
		//根据属性名获取值
		String attributeValue = rootElement.attributeValue("Name");
		System.out.println(attributeValue);
	}
	//8、添加属性:State: GDP="99999亿"
	private static void method8() throws DocumentException, IOException {
		//获取Document对象
		Document document = Dom4JUtils.getDocument();
		//获取根元素
		Element rootElement = document.getRootElement();
		//添加新的属性和对应的值
		rootElement.addAttribute("人口数量", "100000000");
		//写回文件
		Dom4JUtils.write2XML(document);
	}
	
	public static void treeWalk(Element element) {
		//输出元素的名称
		System.out.println(element.getName());
		//获取指定元素的所有子元素
		List<Element> es = element.elements();
		for (Element e : es) {
			treeWalk(e);
		}
	}
	/*
	 * 遍历树中所有节点
	 * 参数列表:根节点 Element root
	 * 返回值:void
	 */
	public static void myTreeRecur(Element root){
		System.out.println(root.getName());
		//获得根元素下所有字节点
		List<Element> elements = root.elements();
		//遍历所有子节点
		for (int i = 0; i < elements.size(); i++) {
			myTreeRecur(elements.get(i));
		}
	}
}
/*
 * 自定义工具类
 */
public class Dom4JUtils {
	//私有化构造器
	private Dom4JUtils(){}
	//定义静态方法
    public static Document getDocument() throws DocumentException, IOException {
        SAXReader reader = new SAXReader();
        //当前包路径下的city.xml
//        Document document = reader.read("src/com/itheima_01_overwrite/city.xml");
        //当前项目路径下的city.xml
//        Document document = reader.read(new FileInputStream("city.xml"));
        Document document = reader.read(new FileInputStream("src/com/itheima_01_overwrite/city.xml"));
        return document;
    }
	public static void write2XML(Document document) throws IOException {
		OutputFormat format = OutputFormat.createPrettyPrint();
		//format.setEncoding("UTF-8");//默认的编码就是UTF-8
		XMLWriter writer = new XMLWriter( new FileOutputStream("src/com/itheima_01_overwrite/city.xml"), format );
        writer.write(document);
	}
}
<?xml version="1.0" encoding="UTF-8"?>

<State Code="37" Name="河南" description="郑州" GDP="99999亿"> 
  <City Name="河南"/>  
  <City> 
    <Name>郑州</Name>  
    <Region>高薪区</Region> 
  </City>  
  <City>三门峡</City>  
  <City>洛阳</City>  
  <City>襄阳</City>  
  <City>南阳</City> 
</State>

XML基础知识

xml的语法
    (1)xml的文档声明(***)
        * 创建一个文件 后缀名是 .xml
        * 如果写xml,第一步 必须要有 一个文档声明(写了文档声明之后,表示写xml文件的内容)
        ** <?xml version="1.0" encoding="gbk"?>
        *** 文档声明必须写在 第一行第一列

        * 属性
            - version:xml的版本 1.0(使用) 1.1
            - encoding:xml编码 gbk  utf-8  iso8859-1(不包含中文)
            - standalone:是否需要依赖其他文件 yes/no
        
        * xml的中文乱码问题解决
            ** 画图分析乱码问题
            ** 保存时候的编码和设置打开时候的编码一致,不会出现乱码

    (2)定义元素(标签)(***)
    (3)定义属性(***)
    (4)注释(***)
    (5)特殊字符(***)
    (6)CDATA区(了解)
    (7)PI指令(了解)

xml的元素(标签)定义(*****)
    ** 标签定义

    ** 标签定义有开始必须要有结束:<person></person>
    ** 标签没有内容,可以在标签内结束 ; <aa/>
    ** 标签可以嵌套,必须要合理嵌套
        *** 合理嵌套 <aa><bb></bb></aa>
        *** 不合理嵌套 <aa><bb></aa></bb>: 这种方式是不正确的
    ** 一个xml中,只能有一个根标签,其他标签都是这个标签下面的标签

    ** 在xml中把空格和换行都当成内容来解析,
        **** 下面这两段代码含义是不一样的
        * <aa>1111111</aa>
        * <aa>
            11111111111
          </aa>
    
    ** xml标签可以是中文

    ** xml中标签的名称规则
        (1)xml代码区分大小写
            <p> <P>:这两个标签是不一样的
        (2)xml的标签不能以数字和下划线(_)开头
            <2a> <_aa>: 这样是不正确的
        (3)xml的标签不能以xml、XML、Xml等开头
            <xmla> <XmlB> <XMLC>: 这些都是不正确的
        (4)xml的标签不能包含空格和冒号
            <a b> <b:c> : 这些是不正确的

xml中属性的定义(*****)
    * html是标记型文档,可以有属性
    * xml也是标记型文档,可以有属性

    * <person id1="aaa" id2="bbb"></person>

    ** 属性定义的要求
        (1)一个标签上可以有多个属性
            <person id1="aaa" id2="bbb"></person>
        (2)属性名称不能相同
            <person id1="aaa" id1="bbb"></person>:这个是不正确,不能有两个id1
        (3)属性名称和属性值之间使用= ,属性值使用引号包起来 (可以是单引号,也可以是双引号 )
        (4)xml属性的名称规范和元素的名称规范一致

xml中的注释(*****)
    * 写法 <!-- xml的注释 -->
    ** 注意的地方
        **** 注释不能嵌套
            <!--  <!-- -->  -->
            <!-- <!-- <sex>nv</sex>--> -->
    ** 注释也不能放到第一行,第一行第一列必须放文档声明

xml中的特殊字符(*****)
    * 如果想要在xml中现在 a<b ,不能正常显示,因为把<当做标签
    * 如果就想要显示,需要对特殊字符 < 进行转义
    ** <    &lt;
       >    &gt;
 
CDATA区(了解)
    * 可以解决多个字符都需要转义的操作 if(a<b && b<c && d>f) {}
    * 把这些内容放到CDATA区里面,不需要转义了
    ** 写法
        <![CDATA[ 内容  ]]>
        - 代码
        <![CDATA[ <b>if(a<b && b<c && d>f) {}</b> ]]>
    ** 把特殊字符,当做文本内容,而不是标签

PI指令(处理指令)(了解)
    * 可以在xml中设置样式
    * 写法: <?xml-stylesheet type="text/css" href="css的路径"?>

    * 设置样式,只能对英文标签名称起作用,对于中文的标签名称不起作用的。

    ** xml的语法的总结
        所有 XML 元素都须有关闭标签
        XML 标签对大小写敏感
        XML 必须正确地嵌套顺序
        XML 文档必须有根元素(只有一个)
        XML 的属性值须加引号
        特殊字符必须转义 --- CDATA
        XML 中的空格、回车换行会解析时被保留

xml的约束
    * 为什么需要约束?
    ** 比如现在定义一个person的xml文件,只想要这个文件里面保存人的信息,比如name age等,但是如果在xml文件中
    写了一个标签<猫>,发现可以正常显示,因为符合语法规范。但是猫肯定不是人的信息,xml的标签是自定义的,需要技术来
    规定xml中只能出现的元素,这个时候需要约束。

    * xml的约束的技术 : dtd约束 和 schema约束 xsd (看懂)

dtd的快速入门
    * 创建一个文件 后缀名 .dtd

    步骤:
        (1)看xml中有多少个元素 ,有几个元素,在dtd文件中写几个 <!ELEMENT>
        (2)判断元素是简单元素还是复杂元素
            - 复杂元素:有子元素的元素
                <!ELEMENT 元素名称 (子元素)>
            - 简单元素:没有子元素
                <!ELEMENT 元素名称 (#PCDATA)>
        (3)需要在xml文件中引入dtd文件
            <!DOCTYPE 根元素名称 SYSTEM "dtd文件的路径">
    
    ** 打开xml文件使用浏览器打开的,浏览器只负责校验xml的语法,不负责校验约束

    ** 如果想要校验xml的约束,需要使用工具(myeclipse工具)

    ** 打开myeclipse开发工具
        *** 创建一个项目 day05
        *** 在day05的src目录下面创建一个xml文件和一个dtd文件
        *** 当xml中引入dtd文件之后,比如只能出现name age,多写了一个a,会提示出错

dtd的三种引入方式
    (1)引入外部的dtd文件
        <!DOCTYPE 根元素名称 SYSTEM "dtd路径">
    (2)使用内部的dtd文件
        - <!DOCTYPE 根元素名称 [
            <!ELEMENT person (name,age)>
            <!ELEMENT name (#PCDATA)>
            <!ELEMENT age (#PCDATA)>
        ]>
    (3)使用外部的dtd文件(网络上的dtd文件)
        <!DOCTYPE 根元素 PUBLIC "DTD名称" "DTD文档的URL">
        - 后面学到框架 struts2 使用配置文件 使用 外部的dtd文件
        - <!DOCTYPE struts PUBLIC   "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"    
           "http://struts.apache.org/dtds/struts-2.0.dtd">

使用dtd定义元素
    * 语法: <!ELEMENT 元素名 约束>

    * 简单元素:没有子元素的元素
        <!ELEMENT name (#PCDATA)>
        *** (#PCDATA): 约束name是字符串类型
        *** EMPTY : 元素为空(没有内容)
            - <sex></sex>
        *** ANY:任意
    * 复杂元素:
        <!ELEMENT person (name,age,sex,school)>
            - 子元素只能出现一次
        * <!ELEMENT 元素名称 (子元素)>

        * 表示子元素出现的次数
            + : 表示一次或者多次
            ? :表示零次或者一次
            * :表示零次或者多次
        
        * 子元素直接使用逗号进行隔开 ,
            ** 表示元素出现的顺序

        * 子元素直接使用|隔开
            ** 表示元素只能出现其中的任意一个
    
使用dtd定义属性
    * 语法: <!ATTLIST 元素名称
            属性名称 属性类型 属性的约束
         >
    
    * 属性类型
        - CDATA: 字符串
            -     <!ATTLIST birthday
                ID1 CDATA #REQUIRED
            >

        - 枚举 : 表示只能在一定的范围内出现值,但是只能每次出现其中的一个
            ** 红绿灯效果
            ** (aa|bb|cc)
            - <!ATTLIST age
                ID2 (AA|BB|CC)  #REQUIRED
            >

        - ID: 值只能是字母或者下划线开头
            - <!ATTLIST name 
                ID3 ID   #REQUIRED
            >
    
    * 属性的约束
        - #REQUIRED:属性必须存在

        - #IMPLIED:属性可有可无

        - #FIXED: 表示一个固定值 #FIXED "AAA"
            - 属性的值必须是设置的这个固定值
            - <!ATTLIST sex
                ID4 CDATA #FIXED "ABC"
            >
        - 直接值
            * 不写属性,使用直接值
            * 写了属性,使用设置那个值
            - <!ATTLIST school
                ID5 CDATA "WWW"
            >

实体的定义
    * 语法: <!ENTITY 实体名称 "实体的值">
    *** <!ENTITY TEST "HAHAHEHE">
    *** 使用实体 &实体名称;  比如 &TEST;

    ** 注意
        * 定义实体需要写在内部dtd里面,
          如果写在外部的dtd里面,有某些浏览器下,内容得不到

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值