XML的学习目标:
1.能够用xml描述有层次的数据关系.
2.能够用解析器读取xml中的有层次关系的数据.(parser)
一、XML是什么?作用是什么?
1、XML是指可扩展标记语言(eXtensibleMarkupLanguage),用户自定义的标签.相对于HTML来讲的。
2、XML被设计的宗旨是表示数据。HTML是用来显示数据的。目前经常使用的XML版本是1.0
3、XML除了表示数据外。在实际的企业开发中,主要用XML作为程序的配置文件。
二、XML的基本语法
1)文档声明
编写xml文件的时候,必须要添加声明.声明必须要出现在第一行,之前连空行都不能有.
最简单的文档声明:<?xmlversion="1.0"?>
<?xmlversion="1.0"encoding="gbk"?>
standalone属性,用来说明xml文档是否独立.
2)元素
a)一个xml的元素也可以叫做标签.这个必须要有开始和结束标签.
标签要合理的嵌套.不能够没爹没娘的嵌套.
一个xml文档必须有且仅有一个根标签哦.
b)xml中的空格和换行会被当做元素内容去处理,所以在实际开发过程中,需要将
空格和换行给去掉.响应的写成这样一种形式:
例如:<中国><北京/></中国>
3)属性
一个xml标签可以有多个属性,语法类似html中设置属性的语法.
<mytagname="value"/>
<mytag>
<name>
<firstname></firstnamename>
<secondname></secondname>
</name>
</mytag>
4注释
注释的格式:<!--这是注释哦-->
注释也不能够嵌套.
xml中的注释不能够出现在第一行.
5.CDATA区、
CDATA(CharacterData)的缩写.实际开发过程中,一些数据可能不想让解析引擎处理.
就可以把它们放到CDATA区中
<![CDATA[
文本内容
]]>
特殊字符:
&&ersand
>>greatthan
<<lessthan
""quotation
''apostrophe
6.处理指令(processinginstruction)(PI)
<?xml-stylesheettype="text/css"href="s.css"?>
文档的声明也是一个处理指令
三、XML的约束
1、格式良好的XML文档:符合XML语法的。
2、有效的XML文档:遵循约束规范的。
格式良好的不一定是有效的,但有效的必定格式良好。
四、DTD的基本语法(看懂即可)
1、DTD:DocumentTypeDefinition
2、作用:约束XML的书写规范。
3、DTD文件保存到磁盘时,必须使用UTF-8编码
4、如何引入外部的DTD文档来约束当前的XML文档
DTD文件在本地:<!DOCTYPE根元素名称SYSTEM"DTD文件的路径">
DTD文件在网络上:<!DOCTYPE根元素名称PUBLIC"DTD名称""DTD的路径URL">
5、DTD的语法细节
5.1定义元素
语法:<!ELEMENT元素名称使用规则>
使用规则:
(#PCDATA):指示元素的主体内容只能是普通的文本.(ParsedCharacterData)
EMPTY:指示元素的不能有主体内容。
ANY:用于指示元素的主体内容为任意类型
(子元素):指示元素中包含的子元素
如果子元素用逗号分开,说明必须按照声明顺序去编写XML文档
如果子元素用“|”分开,说明任选其一。
用+、*、?来表示元素出现的次数
5.2定义元素的属性(attribute)
语法:<!ATTLIST哪个元素的属性
属性值类型:
CDATA:说明该属性的取值为一个普通文本
ENUMERATED(DTD没有此关键字):
语法:<!ATTLIST元素名称(值1|值2)"值1">
ID:属性的取值不能重复
设置说明:
#IMPLIED:属性可有可无
#FIXED:表示属性的取值为一个固定值语法:#FIXED"固定值"
直接值:表示属性的取值为该默认值
5.2定义实体
关键字ENTITY
实体的定义分为引用实体和参数实体
引用实体:
作用:在DTD中定义,在XML中使用
在XML中使用:&实体名称;
参数实体:
作用:在DTD中定义,在DTD中使用
在DTD中使用:%实体名称;
五、XML解析方式概述
1、常用XML的解析方式:DOM和SAX
DOM:DocumentObjectModel是W3C推荐使用的解析方式
SAX:SimpleAPIforXML。非官方标准。
2、常用解析开发包:
JAXP:SUN推出的实现,能进行DOM和SAX方式解析
Dom4J
JDom等
六、JAXP进行DOM解析
JAXP的API都在JavaSE中。
org.w3c.dom:提供DOM方式解析XML的标准接口
org.xml.sax:提供SAX方式解析XML的标准接口
javax.xml:提供了解析XML文档的类
XML编程(CRUD)
DOM解析:
获得JAXP中的DOM解析器:
l调用DocumentBuilderFactory.newInstance()方法得到创建DOM解析器的工厂。
l调用工厂对象的newDocumentBuilder方法得到DOM解析器对象。
l调用DOM解析器对象的parse()方法解析XML文档,得到代表整个文档的Document对象,进而可以利用DOM特性对整个XML文档进行操作了。
DOM模型(documentobjectmodel)
DOM解析器在解析XML文档时,会把文档中的所有元素,按照其出现的层次关系,解析成一个个Node对象(节点)。
在dom中,节点之间关系如下:
位于一个节点之上的节点是该节点的父节点(parent)
一个节点之下的节点是该节点的子节点(children)
同一层次,具有相同父节点的节点是兄弟节点(sibling)
一个节点的下一个层次的节点集合是节点后代(descendant)
父、祖父节点及所有位于节点上面的,都是节点的祖先(ancestor)
Node对象
Node对象提供了一系列常量来代表结点的类型,当开发人员获得某个Node类型后,就可以把Node节点转换成相应的节点对象(Node的子类对象),以便于调用其特有的方法。(查看API文档)
Node对象提供了相应的方法去获得它的父结点或子结点。编程人员通过这些方法就可以读取整个XML文档的内容、或添加、修改、删除XML文档的内容了。
更新XML文档
avax.xml.transform包中的Transformer类用于把代表XML文件的Document对象转换为某种格式后进行输出,例如把xml文件应用样式表后转成一个html文档。利用这个对象,当然也可以把Document对象又重新写入到一个XML文件中。
Transformer类通过transform方法完成转换操作,该方法接收一个源和一个目的地。我们可以通过:
javax.xml.transform.dom.DOMSource类来关联要转换的document对象,
用javax.xml.transform.stream.StreamResult对象来表示数据的目的地。
Transformer对象通过TransformerFactory获得。
实例代码:
- <?xml@H_301_1746@version="1.0"@H_301_1746@encoding="UTF-8"@H_301_1746@standalone="no"?>
- <!DOCTYPEchina[
- <!ELEMENTchina(itheima,itcast)>
- <!ELEMENTitheima(teacher+)>
- <!ELEMENTitcast(teacher+)>
- <!ELEMENTteacher(name,age,teach)>
- <!ELEMENTname(#PCDATA)>
- <!ELEMENTage(#PCDATA)>
- <!ELEMENTteach(#PCDATA)>
- <!ATTLISTteacheridID#required>
- ]>
- <china>
- <itheima>
- <teacher@H_301_1746@id="a1">
- <name>张孝祥</name>
- <age>38</age>
- <teach>javaee</teach>
- </teacher>
- <teacher@H_301_1746@id="a2">
- <name>方立勋</name>
- <age>36</age>
- <teach>javaweb</teach>
- <teacher@H_301_1746@id="a3">
- <name>付东</name>
- <age>34</age>
- <teach>andriod</teach>
- <!--验证成功-->
- </itheima>
- <itcast>
- <teacher@H_301_1746@id="b1">
- <name>张磊</name>
- <age>34</age>
- <teach>web基础</teach>
- </teacher>
- <teacher@H_301_1746@id="b2">
- <name>韩顺平</name>
- <age>39</age>
- <teach>linux</teach>
- <teacher@H_301_1746@id="b3">
- <name>张昭廷</name>
- <teach>javaweb</teach>
- </itcast>
- </china>
-------------------------------------------------
- packagecn.itheima.dom;
- importjavax.xml.parsers.DocumentBuilder;
- importjavax.xml.parsers.DocumentBuilderFactory;
- importjavax.xml.transform.Transformer;
- importjavax.xml.transform.TransformerFactory;
- importjavax.xml.transform.dom.DOMSource;
- importjavax.xml.transform.stream.StreamResult;
- importorg.junit.Assert;
- importorg.junit.Test;
- importorg.w3c.dom.Document;
- importorg.w3c.dom.Element;
- importorg.w3c.dom.Node;
- importorg.w3c.dom.NodeList;
- publicclassDOMTeast{
- /**
- *@paramargs
- *@throwsException
- */
- publicstaticvoidmain(String[]args)throwsException{
- //TODOAuto-generatedmethodstub
- //test1();
- //readAtt();
- //addNode();
- //deleteNode();
- //binaLiNode();
- //refreshNode();
- }
- //6.打印所有元素节点的名称.遍历
- publicstaticvoidbinaLiNode()throwsException{
- Documentdocument=getDocument();
- listNode(document);
- privatestaticvoidlistNode(Nodenode){
- //TODOAuto-generatedmethodstub
- if(node.getNodeType()==Node.ELEMENT_NODE){
- System.out.println(node.getNodeName());
- }
- NodeListnl=node.getChildNodes();
- for(inti=0;i<nl.getLength();i++){
- Nodenode1=nl.item(i);
- listNode(node1);
- //5.更新节点:<teach>javaee</teach>
- publicstaticvoidrefreshNode()throwsException{
- Documentdocument=getDocument();
- NodeListnodeList=document.getElementsByTagName("teach");
- /*for(inti=0;i<nodeList.getLength();i++){
- Nodenode=nodeList.item(i);
- if(node.getTextContent().equals("javaee")){
- node.getParentNode().setTextContent("android");
- }
- }*/
- nodeList.item(0).getParentNode().setTextContent("android");
- refreshXML(document);
- //4.删除节点:<teach>javaee</teach>
- @Test
- publicstaticvoiddeleteNode()throwsException{
- NodeListnodeList=document.getElementsByTagName("teach");
- for(inti=0;i<nodeList.getLength();i++){
- Nodenode=nodeList.item(i);
- if(node.getTextContent().equals("javaee")){
- node.getParentNode().removeChild(node);
- //3.添加节点:<售价>59.00</售价>
- publicstaticvoidaddNode()throwsException{
- //添加吴超标签题,然后设置属性id为5;
- Elementelement=document.createElement("teacher");
- //element.setAttribute("id","5");
- element.setTextContent("test");
- Nodeitem=document.getElementsByTagName("itheima").item(0);
- item.appendChild(element);
- refreshXML(document);
- //2.读取属性值,这个思路没问题,测试结果不行!!!--
- publicstaticvoidreadAtt()throwsException{
- NodeListtagName=document.getElementsByTagName("name");
- /*for(inti=0;i<tagName.getLength();i++){
- Elementitem=(Element)tagName.item(i);
- //测试用
- //System.out.println(item.getLocalName());
- Objectatt=item.getAttribute("color");
- System.out.println(att);
- Assert.assertEquals("red",att);
- }*/
- Elementitem=(Element)tagName.item(0);
- Objectatt=item.getAttribute("color");
- System.out.println(att);
- Assert.assertEquals("red",0); background-color:inherit">//*1.读取节点的文本内容
- publicstaticvoidtest1()throwsException{
- NodeListtagName=document.getElementsByTagName("teach");
- for(intx=0;x<tagName.getLength();x++){
- Nodenode=tagName.item(x);
- //getTextContent获取标签的标签体
- Stringstring=node.getTextContent();
- System.out.println(string);
- /*javaee
- javaweb
- andriod
- web基础
- linux
- javaweb*/
- //-----------------------------------------
- publicstaticDocumentgetDocument()throwsException{
- //首先拿到一个documentbuilderfactory对象.
- DocumentBuilderFactoryfactory=DocumentBuilderFactory.newInstance();
- //通过factory对象拿到一个documentbuilder对象.
- DocumentBuilderbuilder=factory.newDocumentBuilder();
- //通过builder的parse方法获得一个document对象.
- Documentdocument=builder.parse("src\\itheima.xml");
- returndocument;
- publicstaticvoidrefreshXML(Documentdoc)throwsException{
- //如何更新xml文件从内存中到xml文档.
- //首先要拿到一个工厂
- TransformerFactoryfactory=TransformerFactory.newInstance();
- //拿到工厂之后在获得一个transformer
- Transformertransformer=factory.newTransformer();
- transformer.transform(newDOMSource(doc),newStreamResult("src/itheima.xml"));
- }
七、JAXP进行SAX解析
在使用DOM解析XML文档时,需要读取整个XML文档,在内存中构架代表整个DOM树的Doucment对象,从而再对XML文档进行操作。此种情况下,如果XML文档特别大,就会消耗计算机的大量内存,并且容易导致内存溢出。(java中虚拟机默认开辟的内存空间)outofmemort(OOM)
SAX解析允许在读取文档的时候,即对文档进行处理,而不必等到整个文档装载完才对文档进行操作。
SAX采用事件处理的方式解析XML文件,利用SAX解析XML文档,涉及两个部分:解析器和事件处理器:
解析器可以使用JAXP的API创建,创建出SAX解析器后,就可以指定解析器去解析某个XML文档。
解析器采用SAX方式在解析某个XML文档时,它只要解析到XML文档的一个组成部分,都会去调用事件处理器的一个方法,解析器在调用事件处理器的方法时,会把当前解析到的xml文件内容作为方法的参数传递给事件处理器。
事件处理器由程序员编写,程序员通过事件处理器中方法的参数,就可以很轻松地得到sax解析器解析到的数据,从而可以决定如何对数据进行处理。
SAX方式解析XML文档
使用SAXParserFactory创建SAX解析工厂
SAXParserFactoryspf=SAXParserFactory.newInstance();
通过SAX解析工厂得到解析器对象
SAXParsersp=spf.newSAXParser();
通过解析器对象得到一个XML的读取器
XMLReaderxmlReader=sp.getXMLReader();
设置读取器的事件处理器
xmlReader.setContentHandler(newBookParserHandler());
解析xml文件
xmlReader.parse("book.xml");
******八.Pull解析器
pull解析器是一个第三方的开源api,其解析原理与sax解析原理很相像,都是采用事件驱动的方式.
不同点:pull解析器在每次读取到一段数据之后,需要程序员手动的调用其next()方法,将当前解析到的这一行的"指针"移到下一行.