Day05 xml详解

day05总结

今日内容

  • XML语法
  • XML约束之DTD
  • XML解析器介绍
  • XML解析之JAXP( DOM、SAX )
  • DOM4J
  • Schema

 

一、XML语法

XML概述

 

1 什么是XML

XML全称为Extensible Markup Language, 意思是可扩展的标记语言,它是 SGML(标准通用标记语言)的一个子集。

XML语法上和HTML比较相似,但HTML中的元素是固定的,而XML的标签是可以由用户自定义的。

W3C在1998年2月发布1.0版本

W3C在2004年2月发布1.1版本,但因为1.1版本不能向下兼容1.0版本,所以1.1没有人用。同时,在2004年2月W3C又发布了1.0版本的第三版。我们要学习的还是1.0版本!!!

 

2 W3C组织

W3C是万维网联盟(World Wide Web Consortium)英文的缩写,它成立于1994年10月,以开放论坛的方式来促进开发互通技术(包括规格、指南、软件和工具),开发网络的全部潜能。万维网联盟(W3C)从1994年成立以来,已发布了90多份Web技术规范,领导着Web技术向前发展。

W3C认为自身不是官方组织,因此将它正式发布的规范称为推荐(建议)标准,意思是进一步标准化的建议,但是由于组织自身的权威性往往成为事实上的标准。

 

3 XML的作用

 

4 XML与HTML比较

 

5 XML和properties(属性文件)比较

 

XML语法概述

 

1 XML文档展示

 

 

2 XML文档的组成部分

 

XML文档声明

 

1 什么是xml文档声明

可以把xml文档声明看成是xml文档说明。

最简单的xml文档声明:<?xml version="1.0"?>

  注意,XML是区别大小写,这一点不同与HTML!

 

2 xml文档声明结构

 

XML元素

 

1 XML元素的格式1

 

2 XML元素的格式2

 

3 XML文档的根元素

格式良好的xml文档必须且仅有一个根元素!

 

student1.xml

<?xml version="1.0" encoding="utf-8" standalone="no"?>

<students>

    <student number="1001">

        <name>zhangSan</name>

        <age>23</age>

        <sex>male</sex>

    </student>

    <student number="1002">

        <name>liSi</name>

        <age>32</age>

        <sex>female</sex>

    </student>

</students>

 

student2.xml

<?xml version="1.0" encoding="utf-8" standalone="no"?>

<student number="1001">

    <name>zhangSan</name>

    <age>23</age>

    <sex>male</sex>

</student>

<student number="1002">

    <name>liSi</name>

    <age>32</age>

    <sex>female</sex>

</student>

 

student1.xml是格式良好的xml文档,只有一个根元素,即students元素。

student2.xml不是格式良好的xml文档,有两个根元素,即两个student根元素。

 

4 元素中的空白

xml元素的元素体可以包含文本数据和子元素。

a.xml

<a><b>hello</b></a>

 

b.xml

<a>

<b>

hello

</b>

</a>

 

  a.xml中,<a>元素只有一个子元素,即<b>元素。<b>元素只有一个文本数据,即hello。

b.xml中,<a>元素中第一部分为换行缩进,第二部分为<b>元素,第三部分为换行。b元素的文本数据为换行、缩进、hello、换行、缩进。

其中换行和缩进都是空白,这些空白是为了增强xml文档的可读性。但xml解析器可能会因为空白出现错误的解读,这说明在将来编写解析xml程序时,一定要小心空白。

 

5 元素命名规范

  xml元素名可以包含字母、数字以及一些其它可见字符,但必须遵循下面的一些规范:

 

元素属性

 

 

注释

 

转义字符和CDATA区

因为在xml文档中有些字符是特殊的,不能使用它们作为文本数据。例如:不能使用"<"或">"等字符作为文本数据,所以需要使用转义字符来表示。

例如<a><a></a>,你可能会说,其中第二个<a>是a元素的文本内容,而不是一个元素的开始标签,但xml解析器是不会明白你的意思的。

把<a><a></a>修饰为<a>&lt;a&gt;</a>,这就OK了。

 

  转义字符都是以"&"开头,以";"结束。这与后面我们学习的实体是相同的。

 

CDATA区(CDATA段)

当大量的转义字符出现在xml文档中时,会使xml文档的可读性大幅度降低。这时如果使用CDATA段就会好一些。

在CDATA段中出现的"<"、">"、"""、"'"、"&",都无需使用转义字符。这可以提高xml文档的可读性。

<a><![CDATA[<a>]]></a>

 

  在CDATA段中不能包含"]]>",即CDATA段的结束定界符。

 

处理指令

 

处理指令,简称PI(Processing instruction)。处理指令用来指挥解析器如何解析XML文档内容。

例如,在XML文档中可以使用xml-stylesheet指令,通知XML解析器,应用css文件显示xml文档内容。

<?xml-stylesheet type="text/css" href="a.css"?>

处理指令以"<?"开头,以"?>"结束,这一点与xml文档声明相同。

gj1 {font-size: 200px; color: red;}

gj2 {font-size: 100px; color: green;}

gj3 {font-size: 10px;}

gj4 {font-size: 50px; color: blue;}

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

<?xml-stylesheet type="text/css" href="a.css" ?>

<gjm>

<gj1>中国</gj1>

<gj2>美国</gj2>

<gj3>日本</gj3>

<gj4>英国</gj4>

</gjm>

 

二、XML约束

XML约束概述

  一个XML文档一旦有了约束,那么这个XML文档就只能使用约束中创建的元素及属性。如果约束没有创建<a>元素,那么XML文档就不能使用<a>元素!!!

1 什么是xml约束

因为xml文档是可以自定义元素的,这会让使用xml文档的应用程序无法知道xml文档的真实结构。通常应用程序都会要求xml文件的结构是固定的,以满足自己的需求,这就说明,不同的应用程序要求自己的xml文档必须符合一定的要求。

例如,当使用xml文档作为某个Java swing应用程序的配置文件时,要求xml文档结构如下:

<frame title="test xml" layout="java.awt.BorderLayout">

<bgcolor>

<red>200</red>

<green>0</green>

<blue>0</blue>

</bgcolor>

<size>

<width>300</width>

<heigth>200</heigth>

</size>

<content>

<label>

<text>hello xml</text>

<label>

</content>

</frame>

 

当某个学生管理系统程序需要使用xml文档作为数据库时,要求xml文档结构如下:

<?xml version="1.0" encoding="utf-8" standalone="no"?>

<students>

    <student number="1001">

        <name>zhangSan</name>

        <age>23</age>

        <sex>male</sex>

    </student>

    <student number="1002">

        <name>liSi</name>

        <age>32</age>

        <sex>female</sex>

    </student>

    <student number="1003">

        <name>wangWu</name>

        <age>55</age>

        <sex>male</sex>

    </student>

</students>

 

  xml文档约束是用另一个文件来约束xml文档的结构,例如要求xml文档的根元素必须是<students>,在<students>元素下可以包含0~n个<student>元素,每个<student>元素必须有一个number属性,而且还要有三个子元素,分别为<name>、<age>、<sex>,这三个子元素的内容必须为文本内容,而不能是子元素。

 

2 XML文档约束的类型

xml文档约束有两种类型:dtd和schema

 

DTD是老的XML约束

Schema是新的,用Schema替换掉DTD

 

会读即可!

 

DTD

 

1 什么是DTD

  DTD(Document Type Definition),文档类型定义,用来约束XML文档。例如要求xml文档的根元素必须是<students>,在<students>元素下可以包含0~n个<student>元素,每个<student>元素必须有一个number属性,而且还要有三个子元素,分别为<name>、<age>、<sex>,这三个子元素的内容必须为文本内容,而不能是子元素。

 

2 DTD展示

 

<!ELEMENT students (student+)>

<!ELEMENT student (name,age,sex)>

<!ELEMENT name (#PCDATA)>

<!ELEMENT age (#PCDATA)>

<!ELEMENT sex (#PCDATA)>

 

解读上面DTD:

 

3 在XML文档中指定本地DTD

 

<?xml version="1.0" encoding="utf-8" standalone="no" ?>

<!DOCTYPE students SYSTEM "students.dtd">

<students>

    <student>

        <name>zhangSan</name>

        <age>23</age>

        <sex>male</sex>

    </student>

</students>

<!ELEMENT students (student+)>

<!ELEMENT student (name, age, sex)>

<!ELEMENT name (#PCDATA)>

<!ELEMENT age (#PCDATA)>

<!ELEMENT sex (#PCDATA)>

 

其中<!DOCTYPE students SYSTEM "students.dtd">,表示指定dtd文件。

指定DTD的语法:<!DOCTYPE 根元素 SYSTEM "DTD文件路径">

 

4 在XML文档中指定内部DTD

 

<?xml version="1.0" encoding="utf-8" standalone="no" ?>

<!DOCTYPE students [

<!ELEMENT students (student+)>

<!ELEMENT student (name, age, sex)>

<!ELEMENT name (#PCDATA)>

<!ELEMENT age (#PCDATA)>

<!ELEMENT sex (#PCDATA)>

]>

<students>

    <student>

        <name>zhangSan</name>

        <age>23</age>

        <sex>male</sex>

    </student>

</students>

 

5 在XML文档中指定外部公共DTD

 

 

外部公共DTD是说,DTD由某个公司或权威组织发布,例如如下:

<!DOCTYPE 根元素 PUBLIC "DTD名称" "DTD网址">

当然你需要知道要使用的DTD的名称和网址。如果某个机构公布了DTD,那么一定也会公布DTD的名称和网址。

上面例子中的公共DTD是不存在的。

 

DTD定义元素

 

1 定义元素的语法

使用ELEMENT声明元素:<!ELEMENT 元素名 内容类型内容>

例如:<!ELEMENT name (#PCDATA)>

表示name元素的内容为文本数据

 

2 元素类型

元素类型可以是ANY或EMPTY

<!ELEMENT stu ANY>:表示stu元素的内容可以是任意元素,也可以是文本数据,也可以是文本数据+子元素,反正就是任意。

<!ELEMENT stu EMPTY>:表示stu不能有任何内容,即空元素。例如:<stu/>。

 

3 元素内容

元素内容可以是文本数据,也可以是子元素

<!ELEMENT stu (#PCDATA)>表示stu元素内容为文本,例如:<stu>hello</stu>

  <!ELEMENT stu (name)>表示stu元素内容为name子元素,例如<stu><name></name><stu>,但要注意,如果<name>元素没有声明,那么就会出错。

 

4 子元素出现次数

可以使用"?"、"*"、"+"来指定子元素的出现次数

<!ELEMENT stu (name?)>表示stu元素可以有0~1个name子元素,即name子元素可有可无。

<!ELEMENT stu(name*)>表示stu元素可以有0~n个name子元素;

<!ELEMENT stu(name+)>表示stu元素可以有1~n个name子元素。

 

5 多个子元素

  <!ELEMENT stu (name,age,sex)>表示stu必须有三个子元素,分别是name、age、sex,并且子元素出现的顺序也要与声明的顺序一致。

 

6 枚举子元素

  <!ELEMENT stu (name | age | sex)表示stu只有一个子元素,可以是name、age、sex中的任意一个。

 

7 复合声明1

<!ELEMENT stu (name | age | sex)?>表示stu元素可以有0~1个(name | age | sex),而(name | age | sex)表示name、age、sex其中的一个。

<stu></stu>

<stu><name/></stu>

<stu><age/></stu>

<stu><sex/></stu>

 

8 复合声明2

  <!ELEMENT stu (name | age | sex)*>表示stu元素可以有0~n个(name | age | sex),而(name | age | sex)表示name、age、sex其中的一个。

<stu></stu>

<stu><name/><name/></stu>

<stu><name/><age/><age/></stu>

<stu><name/><age/><name/><sex/><sex/></stu>

 

9 复合声明3

<!ELEMENT stu (name | age | sex)+>表示stu元素可以有1~n个(name | age | sex),而(name | age | sex)表示name、age、sex其中的一个。

<stu><age/></stu>

<stu><name/><name/></stu>

<stu><name/><age/><age/></stu>

<stu><name/><age/><name/><sex/><sex/></stu>

 

10 练习

    

 

<!DOCTYPE 课件 [

<!ELEMENT 章节 (简介, (标题, (段落 | 图片 | 表格 | 说明)+)+)>

<!ELEMENT 简介 (#PCDATA)>

<!ELEMENT 标题 (#PCDATA)>

<!ELEMENT 段落 (#PCDATA)>

<!ELEMENT 图片 (#PCDATA)>

<!ELEMENT 表格 (#PCDATA)>

<!ELEMENT 说明 (#PCDATA)>

<!ELEMENT 课件 (章节+)>

]>

 

  根据上面DTD写xml文档!!!

 

DTD属性定义

 

1 属性定义的格式

  Attribute List

<!ATTLIST 元素名

          属性名1 属性类型 设置说明

          属性名2 属性类型 设置说明

          ...>

<!ATTLIST student number CDATA #REQUIRED>表示student元素的number为文本类型,这个属性是必须的。

最常见的属性类型:CDATA,表示文本类型;

最常见的设置说明1:#REQUIRED,表示属性是必须的。

最常见的设置说明2:#IMPLIED,表示属性是可选的。

 

2 属性类型

 

3 CDATA属性类型

CDATA,即Character Data(字符数据)。表示属性的类型为字符类型!

<!ATTLIST student number CDATA #REQUIRED>表示student元素的number属性是字符数据类型,并且是必须属性。

<student number="czbk_1001">

 

4 Enumerated属性类型

Enumerated不是关键字,定义枚举类型的属性需要给出枚举列表。当属性值为枚举类型时,那么这个属性的取值必须是枚举列表中的一个值。

<!ATTLIST student sex (male | female) #IMPLIED> 表示student的sex属性取值必须是male或者是female。并且这个属性是可选的。

 

 

5 ID属性类型

  一个元素最多只能有一个ID 属性,ID属性用来表示元素唯一性的唯一标识。ID属性就相当与元素的身份证号,必须是唯一标识!

如果把student元素的number属性设定为ID类型,那么每个student元素的number属性值必须是唯一的,并且ID类型的属性值不能以数字开头。

<!ATTLIST student number ID #REQUIRED> 表示student的number属性值是ID类型,这说明student元素的number属性值必须是唯一的,不能和其他student的number属性值相同。

<student number="czbk_1001"/>

<student number="czbk_1002"/>

 

注意:不能以数字开头。

 

如果<a>元素有一个ID属性a

如果<b>元素有一个ID属性b

<a a="abc"/>

<b b="abc"/>

上面也是错误的,因为ID属性的值是不可以相同的。

 

 

6 设置说明

 

三、XML解析器介绍

 

操作XML文档概述

 

1 如何操作XML文档

XML文档也是数据的一种,对数据的操作也不外乎是"增删改查"。也被大家称之为"CRUD"。

 

2 XML解析技术

XML解析方式分为两种:DOM(Document Object Model)和SAX(Simple API for XML)。这两种方式不是针对Java语言来解析XML的技术,而是跨语言的解析方式。例如DOM还在Javascript中存在!

DOM是W3C组织提供的解析XML文档的标准接口,而SAX是社区讨论的产物,是一种事实上的标准。

DOM和SAX只是定义了一些接口,以及某些接口的缺省实现,而这个缺省实现只是用空方法来实现接口。一个应用程序如果需要DOM或SAX来访问XML文档,还需要一个实现了DOM或SAX的解析器,也就是说这个解析器需要实现DOM或SAX中定义的接口。提供DOM或SAX中定义的功能。

 

解析原理

 

1 DOM解析原理

使用DOM要求解析器把整个XML文档装载到一个Document对象中。Document对象包含文档元素,即根元素,根元素包含N多个子元素…

一个XML文档解析后对应一个Document对象,这说明使用DOM解析XML文档方便使用,因为元素与元素之间还保存着结构关系。

优先:使用DOM,XML文档的结构在内存中依然清晰。元素与元素之间的关系保留了下来!

缺点:如果XML文档过大,那么把整个XML文档装载进内存,可能会出现内存溢出的现象!

 

2 设置Java最大内存

运行Java程序,指定初始内存大小,以及最大内存大小。

java -Xms20m -Xmx100m MyClass

 

 

3 SAX解析原理

DOM会一行一行的读取XML文档,最终会把XML文档所有数据存放到Document对象中。SAX也是一行一行的读取XML文档,但是当XML文档读取结束后,SAX不会保存任何数据,同时整个解析XML文档的工作也就结束了。

但是,SAX在读取一行XML文档数据后,就会给感兴趣的用户一个通知!例如当SAX读取到一个元素的开始时,会通知用户当前解析到一个元素的开始标签。而用户可以在整个解析的过程中完成自己的业务逻辑,当SAX解析结束,不会保存任何XML文档的数据。

优先:使用SAX,不会占用大量内存来保存XML文档数据,效率也高。

缺点:当解析到一个元素时,上一个元素的信息已经丢弃,也就是说没有保存元素与元素之间的结构关系,这也大大限制了SAX的使用范围。如果只是想查询XML文档中的数据,那么使用SAX是最佳选择!

 

解析器概述

 

1 什么是XML解析器

DOM、SAX都是一组解析XML文档的规范,其实就是接口,这说明需要有实现者能使用,而解析器就是对DOM、SAX的实现了。一般解析器都会实现DOM、SAX两个规范!

 

JAXP概述

 

1 什么是JAXP

JAXP是由Java提供的,用于隐藏底层解析器的实现。Java要求XML解析器去实现JAXP提供的接口,这样可以让用户使用解析器时不依赖特定的XML解析器。

JAXP本身不是解析器(不是Xerces),也不是解析方式(DOM或SAX),它只是让用户在使用DOM或SAX解析器时不依赖特点的解析器。

当用户使用JAXP提供的方式来解析XML文档时,用户无需编写与特定解析器相关的代码,而是由JAXP通过特定的方式去查找解析器,来解析XML文档。

 

 

2 JAXP对DOM的支持

 

        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

        DocumentBuilder builder = factory.newDocumentBuilder();

        Document doc = builder.parse("src/students.xml");

 

在javax.xml.parsers包中,定义了DOM解析器工厂类DocumentBuilderFactory,用于产生DOM解析器。DocumentBuilderFactory是一个抽象类,它有一个静态方法newInstance(),可以返回一个本类的实例对象。其实该方法返回的是DocumentBuilderFactory类的子类的实例(即工厂实例对象)。那么这个子类又是哪个子类呢?其实这个子类是由XML解析器提供商提供的,不同的厂商提供的工厂类对抽象工厂的实现是不同的。然后由工厂实例创建解析器对象。

那么newInstance()这个方法又是如果找到解析器提供商的工厂类的呢?此方法使用下面有序的查找过程来确定要加载的DocumentBuilderFactory实现类:

 

一、使用javax.xml.parsers.DocumentBuilderFactory系统属性。如果设置了这个系统属性的值,那么newInstance()方法就以这个属性的值来构造这个工厂的实例。通过下面的方法可以设置这个系统属性值。

System.setProperty("javax.xml.parsers.DocumentBuilderFactory", "工厂实现类名字");

我们不建议大家用上面的方法来硬编码这个系统属性的值,如果这样设置,假如将来需要更换解析器,就必需修改代码。

二、如果你没有设置上面的系统属性,newInstance()方法就会采用下面的途径来查找抽象工厂的实现类。第二个途径在查找JRE下的lib子目录下的jaxp.properties文件。如果这个文件存在,那么就读取这个文件。我们可以在%JAVA_HOME%jrelib目录下创建一个jaxp.properties文件。在这个文件中给出一个键值对。如下所示:

javax.xml.parsers.DocumentBuilderFactory=工厂实现类名字

这个key名字必须是javax.xml.parsers.DocumentBuilderFactory,而相对应的值也必须设置类路径。

三、如果通过前两种途径下没有找到工厂的实现类,那么就需要使用服务API。这个服务API实际上是查找一个JAR文件的META-INF services javax.xml.parsers.DocumentBuilderFactory这个文件(该文件无扩展名)。如果找到了这个文件,就以这个文件的内容做为工厂实现类。这种方式被大多数解析器提供商所采用。在它们发布的解析器JAR包中往往会找到上述文件。然后在这个文件当中指定自己解析器的工厂类的名字。我们只需要把这个JAR文件的路径写到类路径(classpath)中就可以了。但要注意的是,如果在你的classpath中有多个解析器的JAR包路径,这时以前面的类路径优先。

四、如果说在前三种途径中都没有找到工厂实现类,那么就使用平台缺省工厂实现类。

在JAXP的早期的版本(5.0以前)中,除了JAXP API外,还包含了一个叫做Crimson的解析器。从JAXP1.2开始,Sun公司对Apache的Xerces解析器重新包装了一下,并将org.apache.xerces包名改为了com.sun.org.apache.xerces.internal,然后在JAXP的开发包中一起提供,作为缺省的解析器。我们所使用的JDK1.5中包含的缺省解析器就是被重新包装过后的Xerces解析器。

 

  在获取到某个特定解析器厂商的DocumentBuilderFactory后,那么这个工厂对象创建出来的解析器对象当然就是自己厂商的解析器对象了。

 

3 JAXP对SAX的支持

 

        SAXParserFactory factory = SAXParserFactory.newInstance();

        SAXParser parser = factory.newSAXParser();

        parser.parse("src/students.xml", new DefaultHandler() {

            public void startDocument() throws SAXException {

                System.out.println("解析开始");

            }

              

            public void endDocument() throws SAXException {

                System.out.println("解析结束");

            }

 

            public void processingInstruction(String target, String data)

                    throws SAXException {

                System.out.println("处理指令");

            }

              

            public void startElement(String uri, String localName, String qName,

                    Attributes atts) throws SAXException {

                System.out.println("元素开始:" + qName);

            }

 

            public void characters(char[] ch, int start, int length)

                    throws SAXException {

                System.out.println("文本内容:" + new String(ch, start, length).trim());

            }

 

            public void endElement(String uri, String localName, String qName)

                    throws SAXException {

                System.out.println("元素结束:" + qName);

            }

        });

 

  JAXP对SAX的支持与JAXP对DOM的支持是相同的,这里就不在赘述!

 

JDOM和DOM4J

 

1 JDOM和DOM4J概述

  JDOM和DOM4J都是针对Java解析XML设计的方式,它们与DOM相似。但DOM不是只针对Java,DOM是跨语言的,DOM在Javascript中也可以使用。而JDOM和DOM4J都是专业为Java而设计的,使用JDOM和DOM4J,对Java程序员而言会更加方便。

 

2 JDOM和DOM4J比较

JDOM与DOM4J相比,DOM4J完胜!!!所以,我们应该在今后的开发中,把DOM4J视为首选。

在2000年,JDOM开发过程中,因为团队建议不同,分离出一支队伍,开发了DOM4J。DOM4J要比JDOM更加全面。

 

3 DOM4J查找解析器的过程

DOM4J首先会去通过JAXP的查找方法去查找解析器,如果找到解析器,那么就使用之;否则会使用自己的默认解析器Aelfred2。

DOM4J对DOM和SAX都提供了支持,可以把DOM解析后的Document对象转换成DOM4J的Document对象,当然了可以把DOM4J的Document对象转换成DOM的Document对象。

DOM4J使用SAX解析器把XML文档加载到内存,生成DOM对象。当然也支持事件驱动的方式来解析XML文档。

XML解析之JAXP(DOM)

 

JAXP获取解析器

 

1 JAXP相关包

JAXP相关开发包:javax.xml

DOM相关开发包:org.w3c.dom

SAX相关开发包:org.xml.sax

 

2 JAXP与DOM、SAX解析器的关系

  JAXP只是作用只是为了让使用者不依赖某一特定DOM、SAX的解析器实现,当使用JAXP API时,使用者直接接触的就是JAXP API,而不用接触DOM、SAX的解析器实现API。

 

3 JAXP获取DOM解析器

  当我们需要解析XML文档时,首先需要通过JAXP API解析XML文档,获取Document对象。然后用户就需要使用DOM API来操作Document对象了。

        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

        factory.setValidating(false);

        DocumentBuilder builder = factory.newDocumentBuilder();

        Document doc = builder.parse("src/students.xml");

 

4 JAXP保存Document

当我们希望把Document保存到文件中去时,可以使用Transformer对象的transform()方法来完成。想获取Transformer对象,需要使用TransformerFactory对象。

与JAXP获取DOM解析器一样,隐藏了底层解析器的实现。也是通过抽象工厂来完成的,这里就不在赘述了。

     TransformerFactory tFactory = TransformerFactory.newInstance();

        Transformer transformer = tFactory.newTransformer();

        trans.setOutputProperty(OutputKeys.ENCODING, "UTF-8");

        trans.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "students.dtd");

        trans.setOutputProperty(OutputKeys.INDENT, "yes");

        Source source = new DOMSource(doc);

        Result result = new StreamResult(xmlName);

        transformer.transform(source, result);

 

 

Transformer类的transform()方法的两个参数类型为:Source和Result,DOMSource是Source的实现类,StreamResult是Result的实现类。

 

5 JAXP创建Document

有时我们需要创建一个Document对象,而不是从XML文档解析而来。这需要使用DocumentBuider对象的newDocument()方法。

        DocumentBuilderFactory factory = DocumentBuilderFactory

                    .newInstance();

        DocumentBuilder builder = factory.newDocumentBuilder();

        Document doc = builder.newDocument();

        doc.setXmlVersion("1.0");

        doc.setXmlStandalone(true);

 

 

5 学习DOM之前,先写两个方法

 

DOM API概述

 

1 Document对应XML文档

无论使用什么DOM解析器,最终用户都需要获取到Document对象,一个Document对象对应整个XML文档。也可以这样说,Document对象就是XML文档在内存中的表示形式。

通常我们最为"关心"的就是文档的根元素。所以我们必须要把Document获取根元素的方法记住:Element getDocumentElement()。然后通过根元素再一步步获取XML文档中的数据。

 

2 DOM API中的类

  在DOM中提供了很多接口,用来描述XML文档中的组成部分。其中包括:文档(Document)、元素(Element)、属性(Attr)、文本(Text)、注释(Comment)、CDATA段(CDATASection)等等。无论是哪种XML文档组成部分,都是节点(Node)的子接口。

 

3 Node方法介绍

 

Node基本方法:

 

Node获取子节点和父节点方法,只有Document和Element才能使用这些方法:

 

Node获取弟兄节点的方法,只有Element才能使用这些方法:

 

Node添加、替换、删除子节点方法

  • Node appendChild(Node newChild):把参数节点newChild添加到当前节点的子节点列表的末尾处。返回值为被添加的子节点newChild对象,方便使用链式操作。如果newChild在添加之前已经在文档中存在,那么就是修改节点的位置了;
  • Node insertBefore(Node newChild, Node refNode):把参数节点newChild添加到当前节点的子节点refNode之前。返回值为被添加的子节点newChild对象,方便使用链式操作。如果refNode为null,那么本方法与appendNode()方法功能相同。如果newChild节点在添加之前已经在文档中存在,那么就是修改节点的位置了。
  • Node removeNode(Node oldChild):从当前节点中移除子元素oldChild。返回值为被添加的子节点oldChild对象,方便使用链式操作。
  • Node replaceNode(Node newChild, Node oldChild):将当前节点的子节点oldChild替换为newChild。

 

Node获取属性集合方法,只有Element可以使用

  • NamedNodeMap getAttributes():返回当前节点的属性集合。NamedNodeMap表示属性的集合,方法如下:
    • int getLength():获取集合中属性的个数;
    • Node item(int index):获取指定下标位置上的属性节点;
    • Node getNamedItem(String name):获取指定名字的属性节点;
    • Node removeNamedItem(String name):移除指定名字的属性节点,返回值为移除的属性节点;
    • Node setNamedItem(Node arg):添加一个属性节点,返回值为添加的属性节点。

 

Node的判断方法

  • boolean hasChildNodes():判断当前节点是否有子节点;
  • boolean hasAttribute():判断当前节点是否有属性。

 

4 Docment方法介绍

创建节点方法

public class SAXTest {

    @Test

    public void testSAX() throws ParserConfigurationException, SAXException, IOException {

        SAXParserFactory factory = SAXParserFactory.newInstance();

        SAXParser parser = factory.newSAXParser();

        parser.parse("src/students.xml", new MyContentHandler());

    }

    private static class MyContentHandler extends DefaultHandler {

        @Override

        public void startDocument() throws SAXException {

            System.out.println("开始解析...");

        }

        @Override

        public void endDocument() throws SAXException {

            System.out.println("解析结束...");

        }

        @Override

        public void startElement(String uri, String localName, String qName,

                Attributes atts) throws SAXException {

            System.out.println(qName + "元素解析开始");

        }

        @Override

        public void endElement(String uri, String localName, String qName)

                throws SAXException {

            System.out.println(qName + "元素解析结束");

        }

        @Override

        public void characters(char[] ch, int start, int length)

                throws SAXException {

            String s = new String(ch, start, length);

            if(s.trim().isEmpty()) {

                return;

            }

            System.out.println("文本内容:" + s);

        }

        @Override

        public void ignorableWhitespace(char[] ch, int start, int length)

                throws SAXException {

              

        }

        @Override

        public void processingInstruction(String target, String data)

                throws SAXException {

            System.out.println("处理指令");

        }

    }

}

 

2 使用SAX打印XML文档

public class SAXTest2 {

    @Test

    public void testSAX() throws

ParserConfigurationException, SAXException, IOException {

        SAXParserFactory factory = SAXParserFactory.newInstance();

        SAXParser parser = factory.newSAXParser();

        parser.parse("src/students.xml", new MyContentHandler());

    }

    private static class MyContentHandler extends DefaultHandler {

        @Override

        public void startDocument() throws SAXException {

            System.out.println("<?xml version='1.0' encoding='utf-8'?>");

        }

 

        @Override

        public void startElement(String uri, String localName, String qName,

                Attributes atts) throws SAXException {

            StringBuilder sb = new StringBuilder();

            sb.append("<").append(qName);

            for(int i = 0; i < atts.getLength(); i++) {

                sb.append(" ");

                sb.append(atts.getQName(i));

                sb.append("=");

                sb.append("'");

                sb.append(atts.getValue(i));

                sb.append("'");

            }

            sb.append(">");

            System.out.print(sb);

        }

 

        @Override

        public void endElement(String uri, String localName, String qName)

                throws SAXException {

            System.out.print("</" + qName + ">");

        }

 

        @Override

        public void characters(char[] ch, int start, int length)

                throws SAXException {

            System.out.print(new String(ch, start, length));

        }

    }

}

 

DOM4J

DOM4J概述

 

1 DOM4J是什么

DOM4J是针对Java开发人员专门提供的XML文档解析规范,它不同与DOM,但与DOM相似。DOM4J针对Java开发人员而设计,所以对于Java开发人员来说,使用DOM4J要比使用DOM更加方便。

DOM4J对DOM和SAX提供了支持,使用DOM4J可以把org.dom4j.document转换成org.w3c.Document,DOM4J也支持基于SAX的事件驱动处理模式。

使用者需要注意,DOM4J解析的结果是org.dom4j.Document,而不是org.w3c.Document。DOM4J与DOM一样,只是一组规范(接口与抽象类组成),底层必须要有DOM4J解析器的实现来支持。

DOM4J使用JAXP来查找SAX解析器,然后把XML文档解析为org.dom4j.Document对象。它还支持使用org.w3c.Document来转换为org.dom4j.Docment对象。

 

2 DOM4J中的类结构

在DOM4J中,也有Node、Document、Element等接口,结构上与DOM中的接口比较相似。但还是有很多的区别:

在DOM4J中,所有XML组成部分都是一个Node,其中Branch表示可以包含子节点的节点,例如Document和Element都是可以有子节点的,它们都是Branch的子接口。

Attribute是属性节点,CharacterData是文本节点,文本节点有三个子接口,分别是CDATA、Text、Comment。

 

3 DOM4J获取Document对象

  使用DOM4J来加载XML文档,需要先获取SAXReader对象,然后通过SAXReader对象的read()方法来加载XML文档:

 

        SAXReader reader = new SAXReader();

//        reader.setValidation(true);

        Document doc = reader.read("src/students.xml");

 

4 DOM4J保存Document对象

保存Document对象需要使用XMLWriter对象的write()方法来完成,在创建XMLWriter时还可以为其指定XML文档的格式(缩进字符串以及是否换行),这需要使用OutputFormat来指定。

 

        doc.addDocType("students", "", "students.dtd");

        OutputFormat format = new OutputFormat(" ", true);

        format.setEncoding("UTF-8");

        XMLWriter writer = new XMLWriter(new FileWriter(xmlName), format);

        writer.write(doc);

        writer.close();

 

5 DOM4J创建Document对象

  DocumentHelper类有很多的createXXX()方法,用来创建各种Node对象。

 

        Document doc = DocumentHelper.createDocument();

 

 

Document操作 (*****)

 

1 遍历students.xml

  涉及的相关方法:

 

分析步骤:

 

2 给学生元素添加<score>子元素

涉及的相关方法:

 

分析步骤:

 

3 为张三添加friend属性,指定为李四学号

涉及方法:

 

分析步骤:

 

4 删除number为ID_1003的学生元素

涉及方法:

 

分析步骤:

 

5 通过List<Student>生成Document并保存

涉及方法:

 

 

分析步骤:

 

把学生转换成Element步骤分析:

 

6 新建赵六学生元素,插入到李四之前

涉及方法:

 

分析步骤:

 

通过名字查找元素:

 

7 其它方法介绍

Node方法:

 

 

Branch方法:

 

 

Document方法:

 

 

Element方法:

 

 

DocumentHelper静态方法介绍:

 

Schema

Schema概述

我们学习Schema的第一目标是:参照Schema的要求可以编写XML文档;

第二目标是:可以自己来定义Schema文档。

1 Schema是什么

XML文档的约束,用来替代DTD。

DTD文档不是XML语法,而Schema本身也是XML文档,这对解析器来说不用再去处理非XML的文档了;

DTD只能表述平台线束,而Schema本身也是XML,所以可以描述结构化的约束信息。

DTD不只约束元素或属性的类型,但Schema可以。例如让age属性的取值在0~100之间。

Schema文档的扩展名为xsd,即XML Schema Definition。

 

 

<!ELEMENT students (student+)>

<!ELEMENT student (name,age,sex)>

<!ELEMENT name (#PCDATA)>

<!ELEMENT age (#PCDATA)>

<!ELEMENT sex (#PCDATA)>

<!ATTLIST student number CDATA #REQUIRED>

 

3 为students.xml编写schema

 

<?xml version="1.0"?>

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

    <xsd:element name="students" type="studentsType"/>

    <xsd:complexType name="studentsType">

        <xsd:sequence>

            <xsd:element name="student" type="studentType" minOccurs="0" maxOccurs="unbounded"/>

        </xsd:sequence>

    </xsd:complexType>

    <xsd:complexType name="studentType">

        <xsd:sequence>

            <xsd:element name="name" type="xsd:string"/>

            <xsd:element name="age">

                <xsd:simpleType>

                    <xsd:restriction base="xsd:integer">

                        <xsd:maxInclusive value="100"/>

                        <xsd:minInclusive value="0"/>

                    </xsd:restriction>

                </xsd:simpleType>

            </xsd:element>

            <xsd:element name="sex">

                <xsd:simpleType>

                    <xsd:restriction base="xsd:string">

                        <xsd:enumeration value=""/>

                        <xsd:enumeration value=""/>

                    </xsd:restriction>

                </xsd:simpleType>

            </xsd:element>

        </xsd:sequence>

        <xsd:attribute name="number" type="xsd:string"/>

    </xsd:complexType>

</xsd:schema>

 

参照Schema编写XML文档

  我们参照上面的Schema文档编写一个studens.xml文件

 

<?xml version="1.0" encoding="utf-8" standalone="no" ?>
<students xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="students.xsd">
    <student number="ID_1001">
        <name>张三</name>
        <age>23</age>
        <sex></sex>
    </student>
    <student number="ID_1002">
        <name>李四</name>
        <age>32</age>
        <sex></sex>
    </student>
    <student number="ID_1003">
        <name>王五</name>
        <age>50</age>
        <sex></sex>
    </student>
</students>

名称空间相关内容

XSD文档中是创建元素和属性的地方;

XML文档中是使用元素和属性的地方。

所以在XML文档中需要说明使用了哪些XSD文档。

1 什么是名称空间

名称空间是用来处理XML元素或属性的名字冲突问题。你可以理解为Java中的包!包的作用就是用来处理类的名字冲突问题。

注意:XML与Java有很大区别,虽然都是处理名字冲突问题,但语法上是有很大区别的。例如在Java中可以使用import来导入类,但你一定要保存你导入的类已经在类路径(classpath)中存在。使用package为当前Java文件中所有类声明名。但XML的名称空间要比Java复杂很多。

我们在下面讲解XML名称空间时,会使用Java包的概念来理解XML的名称空间的概念,所以现在大家就要注意这么几个特性:

2 声明名称空间(导包)

无论是在XML中,还是在XSD中,都需要声明名称空间。这与Java中使用import来导包是一个道理。当然,前提是有包(创建类是使用了package)才可以导,没包就不能导了。如果被定义的元素在声明时没有指定目标名称空间,那么就是在无名称空间中,那么我们在使用这些在无名称空间中的元素时,就不用再去声明名称空间了。

声明名称空间使用xmlns,例如:xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"。这表示声明了一个名称空间,相当与Java中的import。但是,Java中的import的含义是在下面使用的类,如果没有给出包名,那么就是import导入的这个类。而xmlns表示,下面使用xsi为前缀的元素或属性,都是来自http://www.w3.org/2001/XMLSchema-instance名称空间。也就是说给名称空间起了一个简称,这就相当于我们称呼"北京传智播客教育科技有限公司"为"传智"一样。"传智"就是简称。

例如在XSD文件中,xmlns:xsd="http://www.w3.org/2001/XMLSchema"就是声明名称空间,而这个名称空间是W3C的名称空间,无需关联文件就可以直接声明!在XSD文件中所有使用xsd为前面的元素和属性都是来自http://www.w3.org/2001/XMLSchema名称空间。

名称空间命名:一般名称空间都是以公司的URL来命名,即网址!当然也可以给名称空间命名为aa、bb之类的名字,但这可能会导致名称空间的重名问题。

前缀命名:前缀的命名没有什么要求,但一般对http://www.w3.org/2001/XMLSchema名称空间的前缀都是使用xs或xsd。http://www.w3.org/2001/XMLSchema-instance的前缀使用xsi。

在XML文档中声明xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"名称空间的目的是使用xsi中的一个属性:xsi:noNamespaceSchemaLocation,它是用W3C提供的库属性,用来关联XSD文件用的。当然,它只能关联那些没有"目标名称空间"的XSD文件。下面会讲解目标名称空间!

 

3 默认名称空间

所谓默认名称空间就是在声明名称空间时,不指定前缀,也可以理解为前缀为空字符串的意思。这样定义元素时,如果没有指定前缀的元素都是在使用默认名称空间中的元素。

xmlns="http://www.itcast.cn"

当在文档中使用<xxx>时,那么<xxx>元素就是http://www.itcast.cn名称空间中声明的元素。

注意:没有指定前缀的属性不表示在默认名称空间中,而是表示没有名称空间。也就是说,默认名称空间不会涉及到属性,只对元素有效!

XPath(扩展)

XPath概述

 

1 什么是XPath

XPath即为XML路径语言(XML Path Language),它是一种用来确定XML文档中某部分位置的语言。XPath基于XML的树状结构,提供在数据结构树中找寻节点的能力。起初 XPath 的提出的初衷是将其作为一个通用的、介于XPointer与XSL间的语法模型。但是 XPath 很快的被开发者采用来当作小型查询语言。

 

2 DOM4J对XPath的支持

在DOM4J中,Node接口中的三个方法最为常用: 

 

 

自学笔记:

 

day05

 

昨天内容回顾

    1、在末尾添加节点:

        * 创建标签 createElement

        * 创建文本 createTextNode

        * 把文本添加到标签下面 appendChild

    

    2、获取标签下面的子标签的唯一有效方法

        * getElementsByTagName

    

    3、nodeType

        * 标签节点:1

        * 属性节点:2

        * 文本节点:3

    

        * 父节点:parentNode

    

    4、方法

        * appendChild

        * 在某个节点之前插入节点:insertBefore(new,old);

            - 通过父节点插入

        * 删除节点:removeChild方法

            - 通过父节点删除

        * 替换节点:replaceChild(new,old)

            - - 通过父节点替换

 

    5、innerHTML属性

        * 获取文本内容

        * 向标签内设置内容(可以是html代码)

    

    ** 写js的方法的命名

        add1()、add_1()

 

        ** 不要写单一的单词 add()

        ** 不要把下划线放在开始位置 _add()

 

1、表单提交方式

    * 使用submit提交

    <form>

        .....

        <input type="submit" />

    </form>

 

    * 使用button提交表单

        - 代码

        //实现提交方法

        function form1() {

            //获取form

            var form1 = document.getElementById("form1");

            //设置action

            form1.action = "hello.html";

            //提交form表单

            form1.submit();

        }

    

    * 使用超链接提交

        - 代码

        <a href="hello.html?username=123456">使用超链接提交</a>

    

    * onclick:鼠标点击事件

     onchange:改变内容(一般和select一起使用)

 

     onfocus:得到焦点 (ie5、某些版本的ie6)

     onblur:失去焦点

 

2、xml的简介(了解)

    * eXtensible Markup Language:可扩展标记型语言

        ** 标记型语言:html是标记型语言

            - 也是使用标签来操作

        ** 可扩展:

            - html里面的标签是固定,每个标签都有特定的含义 <h1> <br/> <hr/>

            - 标签可以自己定义,可以写中文的标签 <person></person>、<猫></猫>

    

    * xml用途

        ** html是用于显示数据,xml也可以显示数据(不是主要功能)

        ** xml主要功能,为了存储数据

 

    * xml是w3c组织发布的技术

    

    * xml有两个版本 1.0 1.1

        - 使用都是1.0版本,(1.1版本不能向下兼容)

 

3、xml的应用

    * 不同的系统之间传输数据

        ** qq之间数据的传输

        ** 画图分析过程

 

    * 用来表示生活中有关系的数据

        

    * 经常用在文件配置

        * 比如现在连接数据库 肯定知道数据库的用户名和密码,数据名称

        * 如果修改数据库的信息,不需要修改源代码,只要修改配置文件就可以了

        

 

4、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指令(了解)

 

5、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> : 这些是不正确的

 

6、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属性的名称规范和元素的名称规范一致

 

7、xml中的注释(*****)

    * 写法 <!-- xml的注释 -->

    ** 注意的地方

        **** 注释不能嵌套

            <!-- <!-- --> -->

            <!-- <!-- <sex>nv</sex>--> -->

    ** 注释也不能放到第一行,第一行第一列必须放文档声明

 

8、xml中的特殊字符(*****)

    * 如果想要在xml中现在 a<b ,不能正常显示,因为把<当做标签

    * 如果就想要显示,需要对特殊字符 < 进行转义

    ** < &lt;

     > &gt;

 

9、CDATA区(了解)

    * 可以解决多个字符都需要转义的操作 if(a<b && b<c && d>f) {}

    * 把这些内容放到CDATA区里面,不需要转义了

    ** 写法

        <![CDATA[ 内容 ]]>

        - 代码

        <![CDATA[ <b>if(a<b && b<c && d>f) {}</b> ]]>

    ** 把特殊字符,当做文本内容,而不是标签

 

10、PI指令(处理指令)(了解)

    * 可以在xml中设置CSS样式

    * 写法: <?xml-stylesheet type="text/css" href="css的路径"?>

 

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

 

    ** xml的语法的总结

        所有 XML 元素都须有关闭标签

        XML 标签对大小写敏感

        XML 必须正确地嵌套顺序

        XML 文档必须有根元素(只有一个)

        XML 的属性值须加引号

        特殊字符必须转义 --- CDATA

        XML 中的空格、回车换行会解析时被保留

 

11、xml的约束(dtd)

    * 为什么需要约束?

    ** 比如现在定义一个person的xml文件,只想要这个文件里面保存人的信息,比如name age等,但是如果在xml文件中

    写了一个标签<猫>,发现可以正常显示,因为符合语法规范。但是猫肯定不是人的信息,xml的标签是自定义的,需要技术来

    规定xml中只能出现的元素,这个时候需要约束。

 

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

 

12、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,会提示出错

 

13、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">

 

14、使用dtd定义元素

    * 语法: <!ELEMENT 元素名 约束>

 

    * 简单元素:没有子元素的元素

        <!ELEMENT name (#PCDATA)>

        *** (#PCDATA): 约束name是字符串类型

        *** EMPTY : 元素为空(没有内容)

            - <sex></sex>

        *** ANY:任意

    * 复杂元素:

        <!ELEMENT person (name,age,sex,school)>

            - 子元素只能出现一次

        * <!ELEMENT 元素名称 (子元素)>

 

        * 表示子元素出现的次数

            + : 表示一次或者多次,至少要出现一次

            ? :表示出现零次或者一次

            * :表示出现零次或者多次

        

        * 子元素之间使用逗号进行隔开 ,

            ** 表示元素出现的顺序

 

        * 子元素之间使用|隔开

            ** 表示元素只能出现其中的任意一个

    

15、使用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"

            >

 

16、实体的定义

    * 语法: <!ENTITY 实体名称 "实体的值">

    *** <!ENTITY TEST "HAHAHEHE">

    *** 使用实体 &实体名称; 比如 &TEST;

 

    ** 注意

        * 定义实体需要写在内部dtd里面,

         如果写在外部的dtd里面,有某些浏览器下,内容得不到

 

 

17、xml的解析的简介(写到java代码)(***今天最重要的内容*****)

    * xml是标记型文档

    * js使用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(*** 实际开发中****)

    *** jdom组织,针对dom和sax解析器 jdom

 

18、jaxp的api的查看

    ** jaxp是javase的一部分

 

    ** jaxp解析器在jdk的javax.xml.parsers包里面

        ** 四个类:分别是针对dom和sax解析使用的类

        *** dom:

            DocumentBuilder : 解析器类

                - 这个类是一个抽象类,不能new,

                此类的实例可以从 DocumentBuilderFactory.newDocumentBuilder() 方法获取

 

                - 一个方法,可以解析xml parse("xml路径") 返回是 Document 整个文档

                - 返回的document是一个接口,父节点是Node,如果在document里面找不到想要的方法,到Node里面去找

                

                - 在document里面方法

                    getElementsByTagName(String tagname)

                    -- 这个方法可以得到标签

                    -- 返回集合 NodeList

 

                    createElement(String tagName)

                    -- 创建标签

 

                    createTextNode(String data)

                    -- 创建文本

 

                    appendChild(Node newChild)

                    -- 把文本添加到标签下面

 

                    removeChild(Node oldChild)

                    -- 删除节点

 

                    getParentNode()

                    -- 获取父节点

 

                    NodeList list

                    - getLength() 得到集合的长度

                    - item(int index) 根据下标取到具体的值

                    for(int i=0;i<list.getLength();i++) {

                        list.item(i)

                    }

 

                    getTextContent()

                    - 得到标签里面的内容

                

            DocumentBuilderFactory: 解析器工厂

                - 这个类也是一个抽象类,不能new

                newInstance() 获取 DocumentBuilderFactory 的实例。

 

        *** sax:

            SAXParser:解析器类

            SAXParserFactory: 解析器工厂

 

19、使用jaxp实现查询操作

    *** 查询xml中所有的name元素的值

    * 步骤

    //查询所有name元素的值

    /*

     * 1、创建解析器工厂

        DocumentBuilderFactory.newInstance();

     * 2、根据解析器工厂创建解析器

        builderFactory.newDocumentBuilder();

     * 3、解析xml返回document

     *    Document document = builder.parse("src/person.xml");

     * 4、得到所有的name元素

        使用document.getElementsByTagName("name");

     * 5、返回集合,遍历集合,得到每一个name元素

        - 遍历 getLength() item()

        - 得到元素里面值 使用 getTextContent()

     * */

 

     *** 查询xml中第一个name元素的值

     * 步骤

     /*

         * 1、创建解析器工厂

         * 2、根据解析器工厂创建解析器

         * 3、解析xml,返回document

         *

         * 4、得到所有name元素

         * 5、使用返回集合,里面方法 item,下标获取具体的元素

            NodeList.item(下标): 集合下标从0开始

         * 6、得到具体的值,使用 getTextContent方法

         *

         * */

 

20、使用jaxp添加节点

    *** 在第一个p1下面(末尾)添加 <sex>nv</sex>

    **步骤

    /*

         * 1、创建解析器工厂

         * 2、根据解析器工厂创建解析器

         * 3、解析xml,返回document

         *

         * 4、得到第一个p1

         *     - 得到所有p1,使用item方法下标得到

 

         * 5、创建sex标签 createElement

         * 6、创建文本 createTextNode

         * 7、把文本添加到sex下面 appendChild

 

         * 8、把sex添加到第一个p1下面 appendChild

         *

         * 9、回写xml

         * */

 

21、使用jaxp修改节点

    *** 修改第一个p1下面的sex内容是nan

    ** 步骤

    /*

         * 1、创建解析器工厂

         * 2、根据解析器工厂创建解析器

         * 3、解析xml,返回document

         *

         * 4、得到sex item方法

         * 5、修改sex里面的值

            *** setTextContent方法

         *

         * 6、回写xml

         * */

 

22、使用jaxp删除节点

    *** 删除<sex>nan</sex>节点

    ** 步骤

    /*

         * 1、创建解析器工厂

         * 2、根据解析器工厂创建解析器

         * 3、解析xml,返回document

         *

         * 4、获取sex元素

         * 5、获取sex的父节点 使用getParentNode方法

         * 6、删除使用父节点删除 removeChild方法

         *

         * 7、回写xml

         * */

 

23、使用jaxp遍历节点

    ** 把xml中的所有元素名称打印出来

    ** 步骤

    /*

         * 1、创建解析器工厂

         * 2、根据解析器工厂创建解析器

         * 3、解析xml,返回document

         *

         * ====使用递归实现=====

         * 4、得到根节点

         * 5、得到根节点子节点

         * 6、得到根节点子节点的子节点

         * */

    ** 遍历的方法

    //递归遍历的方法

    private static void list1(Node node) {

        //判断是元素类型时候才打印

        if(node.getNodeType() == Node.ELEMENT_NODE) {            

            System.out.println(node.getNodeName());

        }

        

        //得到一层子节点

        NodeList list = node.getChildNodes();

        //遍历list

        for(int i=0;i<list.getLength();i++) {

            //得到每一个节点

            Node node1 = list.item(i);

            //继续得到node1的子节点

            //node1.getChildNodes()

            list1(node1);

        }

    }

原文地址:https://www.cnblogs.com/Prozhu/p/5712757.html