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在2004年2月发布1.1版本,但因为1.1版本不能向下兼容1.0版本,所以1.1没有人用。同时,在2004年2月W3C又发布了1.0版本的第三版。我们要学习的还是1.0版本!!!
2 W3C组织
W3C认为自身不是官方组织,因此将它正式发布的规范称为推荐(建议)标准,意思是进一步标准化的建议,但是由于组织自身的权威性往往成为事实上的标准。
3 XML的作用
4 XML与HTML比较
5 XML和properties(属性文件)比较
XML语法概述
1 XML文档展示
2 XML文档的组成部分
XML文档声明
1 什么是xml文档声明
最简单的xml文档声明:<?xml version="1.0"?>
2 xml文档声明结构
XML元素
1 XML元素的格式1
2 XML元素的格式2
3 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> |
<?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 元素中的空白
<a><b>hello</b></a> |
<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><a></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;} |
<?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文档作为某个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> |
2 XML文档约束的类型
DTD
1 什么是DTD
2 DTD展示
<!ELEMENT students (student+)> <!ELEMENT student (name,age,sex)> <!ELEMENT name (#PCDATA)> <!ELEMENT age (#PCDATA)> <!ELEMENT sex (#PCDATA)> |
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
<?xml version="1.0" encoding="utf-8" standalone="no" ?> <!DOCTYPE students PUBLIC "-//qdmmy6//DTD ST 1.0//ZH" "http://www.qdmmy6.com/xml/dtds/st.dtd"> |
外部公共DTD是说,DTD由某个公司或权威组织发布,例如如下:
<!DOCTYPE 根元素 PUBLIC "DTD名称" "DTD网址">
当然你需要知道要使用的DTD的名称和网址。如果某个机构公布了DTD,那么一定也会公布DTD的名称和网址。
DTD定义元素
1 定义元素的语法
使用ELEMENT声明元素:<!ELEMENT 元素名 内容类型或内容>
2 元素类型
<!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
8 复合声明2
<stu><name/><age/><age/></stu>
<stu><name/><age/><name/><sex/><sex/></stu>
9 复合声明3
<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属性定义
1 属性定义的格式
<!ATTLIST student number CDATA #REQUIRED>表示student元素的number为文本类型,这个属性是必须的。
2 属性类型
3 CDATA属性类型
CDATA,即Character Data(字符数据)。表示属性的类型为字符类型!
<!ATTLIST student number CDATA #REQUIRED>表示student元素的number属性是字符数据类型,并且是必须属性。
4 Enumerated属性类型
Enumerated不是关键字,定义枚举类型的属性需要给出枚举列表。当属性值为枚举类型时,那么这个属性的取值必须是枚举列表中的一个值。
<!ATTLIST student sex (male | female) #IMPLIED> 表示student的sex属性取值必须是male或者是female。并且这个属性是可选的。
5 ID属性类型
一个元素最多只能有一个ID 属性,ID属性用来表示元素唯一性的唯一标识。ID属性就相当与元素的身份证号,必须是唯一标识!
如果把student元素的number属性设定为ID类型,那么每个student元素的number属性值必须是唯一的,并且ID类型的属性值不能以数字开头。
6 设置说明
三、XML解析器介绍
操作XML文档概述
1 如何操作XML文档
XML文档也是数据的一种,对数据的操作也不外乎是"增删改查"。也被大家称之为"CRUD"。
2 XML解析技术
DOM是W3C组织提供的解析XML文档的标准接口,而SAX是社区讨论的产物,是一种事实上的标准。
解析原理
1 DOM解析原理
使用DOM要求解析器把整个XML文档装载到一个Document对象中。Document对象包含文档元素,即根元素,根元素包含N多个子元素…
一个XML文档解析后对应一个Document对象,这说明使用DOM解析XML文档方便使用,因为元素与元素之间还保存着结构关系。
优先:使用DOM,XML文档的结构在内存中依然清晰。元素与元素之间的关系保留了下来!
缺点:如果XML文档过大,那么把整个XML文档装载进内存,可能会出现内存溢出的现象!
2 设置Java最大内存
3 SAX解析原理
优先:使用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"); |
那么newInstance()这个方法又是如果找到解析器提供商的工厂类的呢?此方法使用下面有序的查找过程来确定要加载的DocumentBuilderFactory实现类:
System.setProperty("javax.xml.parsers.DocumentBuilderFactory", "工厂实现类名字");
我们不建议大家用上面的方法来硬编码这个系统属性的值,如果这样设置,假如将来需要更换解析器,就必需修改代码。
javax.xml.parsers.DocumentBuilderFactory=工厂实现类名字
这个key名字必须是javax.xml.parsers.DocumentBuilderFactory,而相对应的值也必须设置类路径。
四、如果说在前三种途径中都没有找到工厂实现类,那么就使用平台缺省工厂实现类。
在获取到某个特定解析器厂商的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概述
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相关包
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中的类
3 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方法介绍
创建节点方法:
- Attr createAttribute(String name):创建属性节点;
- CDATASection createCDATASection(String data):创建CDATA段节点;
- Comment createComment(String data):创建注释;
- Element createElement(String tagName):创建元素节点;
- Text createTextNode(String data):创建文本节点;
获取子元素方法:
5 Element方法介绍
6 Attr方法介绍
SAX
SAX概述
1 SAX解析原理
2 获取SAX解析器
与DOM相同,你应该通过JAXP获取SAX解析器,而不是直接使用特定厂商的SAX解析器。JAXP查找特定厂商的SAX解析器实现的方式与查找DOM解析器实现的方式完全相同,这里就不在赘述了。
SAXParserFactory factory = SAXParserFactory.newInstance();
javax.xml.parsers.SAXParser parser = factory.newSAXParser();
parser.parse("src/students.xml", new MyContentHandler());
上面代码中,MyContentHandler就是我们自己需要编写的ContentHandler的实现类对象。
3 内容处理器
org.xml.sax.ContentHandler中的方法:
- void setDocumentLocator(Locator locator):与定位相关,例如获取行数、实体、标识等信息,我们可以忽略他的存在;
org.xml.sax.helpers.DefualtHandler对ContentHandler做了空实现,所以我们可以自定义内容处理器时可以继承DefaultHandler类。
SAX应用
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使用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对象
doc.addDocType("students", "", "students.dtd"); OutputFormat format = new OutputFormat("\t", 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并保存
6 新建赵六学生元素,插入到李四之前
7 其它方法介绍
Schema
Schema概述
我们学习Schema的第一目标是:参照Schema的要求可以编写XML文档;
1 Schema是什么
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" ?> |
名称空间相关内容
1 什么是名称空间
名称空间是用来处理XML元素或属性的名字冲突问题。你可以理解为Java中的包!包的作用就是用来处理类的名字冲突问题。
我们在下面讲解XML名称空间时,会使用Java包的概念来理解XML的名称空间的概念,所以现在大家就要注意这么几个特性:
2 声明名称空间(导包)
名称空间命名:一般名称空间都是以公司的URL来命名,即网址!当然也可以给名称空间命名为aa、bb之类的名字,但这可能会导致名称空间的重名问题。
3 默认名称空间
所谓默认名称空间就是在声明名称空间时,不指定前缀,也可以理解为前缀为空字符串的意思。这样定义元素时,如果没有指定前缀的元素都是在使用默认名称空间中的元素。
当在文档中使用<xxx>时,那么<xxx>元素就是http://www.itcast.cn名称空间中声明的元素。
注意:没有指定前缀的属性不表示在默认名称空间中,而是表示没有名称空间。也就是说,默认名称空间不会涉及到属性,只对元素有效!
XPath(扩展)
XPath概述
1 什么是XPath
2 DOM4J对XPath的支持
* 在某个节点之前插入节点:insertBefore(new,old);
var form1 = document.getElementById("form1");
<a href="hello.html?username=123456">使用超链接提交</a>
* eXtensible Markup Language:可扩展标记型语言
- html里面的标签是固定,每个标签都有特定的含义 <h1> <br/> <hr/>
- 标签可以自己定义,可以写中文的标签 <person></person>、<猫></猫>
** html是用于显示数据,xml也可以显示数据(不是主要功能)
* 比如现在连接数据库 肯定知道数据库的用户名和密码,数据名称
* 如果修改数据库的信息,不需要修改源代码,只要修改配置文件就可以了
* 如果写xml,第一步 必须要有 一个文档声明(写了文档声明之后,表示写的是xml文件的内容)
** <?xml version="1.0" encoding="gbk"?>
- encoding:xml编码 gbk utf-8 iso8859-1(不包含中文)
- standalone:是否需要依赖其他文件 yes/no
** 标签定义有开始必须要有结束:<person></person>
*** 不合理嵌套 <aa><bb></aa></bb>: 这种方式是不正确的
** 一个xml中,只能有一个根标签,其他标签都是这个标签下面的标签
<xmla> <XmlB> <XMLC>: 这些都是不正确的
* <person id1="aaa" id2="bbb"></person>
<person id1="aaa" id2="bbb"></person>
<person id1="aaa" id1="bbb"></person>:这个是不正确,不能有两个id1
(3)属性名称和属性值之间使用= ,属性值使用引号包起来 (可以是单引号,也可以是双引号 )
<!-- <!-- <sex>nv</sex>--> -->
* 如果想要在xml中现在 a<b ,不能正常显示,因为把<当做标签
* 可以解决多个字符都需要转义的操作 if(a<b && b<c && d>f) {}
<![CDATA[ <b>if(a<b && b<c && d>f) {}</b> ]]>
* 写法: <?xml-stylesheet type="text/css" href="css的路径"?>
* 设置样式,只能对英文标签名称起作用,对于中文的标签名称不起作用的。
** 比如现在定义一个person的xml文件,只想要这个文件里面保存人的信息,比如name age等,但是如果在xml文件中
写了一个标签<猫>,发现可以正常显示,因为符合语法规范。但是猫肯定不是人的信息,xml的标签是自定义的,需要技术来
* xml的约束的技术 : dtd约束 和 schema约束 (看懂)
(1)看xml中有多少个元素 ,有几个元素,就在dtd文件中写几个 <!ELEMENT>
<!DOCTYPE 根元素名称 SYSTEM "dtd文件的路径">
** 打开xml文件使用浏览器打开的,浏览器只负责校验xml的语法,不负责校验约束
** 如果想要校验xml的约束,需要使用工具(myeclipse工具)
*** 在day05的src目录下面创建一个xml文件和一个dtd文件
*** 当xml中引入dtd文件之后,比如只能出现name age,多写了一个a,会提示出错
<!DOCTYPE 根元素名称 SYSTEM "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">
<!ELEMENT person (name,age,sex,school)>
- 枚举 : 表示只能在一定的范围内出现值,但是只能每次出现其中的一个
- #FIXED: 表示一个固定值 #FIXED "AAA"
17、xml的解析的简介(写到java代码)(***今天最重要的内容*****)
- 根据html的层级结构,在内存中分配一个树形结构,把html的标签,属性和文本都封装成对象
- document对象、element对象、属性对象、文本对象、Node节点对象
* 根据xml的层级结构在内存中分配一个树形结构,把xml的标签,属性和文本都封装成对象
- 从上到下,一行一行的解析,解析到某一个对象,返回该对象名称
** 不同的公司和组织提供了 针对dom和sax方式的解析器,通过api方式提供
*** dom4j组织,针对dom和sax解析器 dom4j(*** 实际开发中****)
** jaxp解析器在jdk的javax.xml.parsers包里面
此类的实例可以从 DocumentBuilderFactory.newDocumentBuilder() 方法获取
- 一个方法,可以解析xml parse("xml路径") 返回是 Document 整个文档
- 返回的document是一个接口,父节点是Node,如果在document里面找不到想要的方法,到Node里面去找
getElementsByTagName(String tagname)
for(int i=0;i<list.getLength();i++) {
newInstance() 获取 DocumentBuilderFactory 的实例。
DocumentBuilderFactory.newInstance();
builderFactory.newDocumentBuilder();
* Document document = builder.parse("src/person.xml");
使用document.getElementsByTagName("name");
* 5、使用返回集合,里面方法 item,下标获取具体的元素
* 6、得到具体的值,使用 getTextContent方法
*** 在第一个p1下面(末尾)添加 <sex>nv</sex>
* 8、把sex添加到第一个p1下面 appendChild
* 5、获取sex的父节点 使用getParentNode方法
private static void list1(Node node) {
if(node.getNodeType() == Node.ELEMENT_NODE) {
System.out.println(node.getNodeName());
NodeList list = node.getChildNodes();