XML:Extensible Markup Language 用标记来修饰文本信息 标签没有预定义,可以自定义 数据相关的技术,企业开发中常用来存储数据和传输数据(而非显示数据),或者作为框架的配置文件,且与任何编程语言无关。 应用:1.充当数据库,保存数据信息 2.AJAX,WebService,网络中传输数据,可以使用xml格式 使用xml描述复杂的关系模型数据 XML语法: 1.文档声明 <?xml version="1.0" encoding="UTF-8" standalone="yes"?> encoding属性用于指定文档中的字符编码,如果没有指定该属性,默认采用ISO-8859-1(不支持中文数据) 如果encoding编码和文件本身的编码不一致,在IE无法解析该xml中的字符,会报错。 standalone属性表示该文档是否依赖外部文件 2.元素 每个元素标签都必须结束,元素标签不能交叉嵌套,有且仅有一个根标签(格式良好的xml文档规范) xml文档中的空格和换行都会被xml解析器解析处理的 3.属性 写在元素上,属性值用双引号或者单引号包含起来 4.注释 <!-- ... --> 存在于正文,不能在文档声明和处理指令之前 5.<![CDATA[...]]> 不会被xml解析器处理 转义字符 < less than < > greater than > <a> <a> 特殊字符必须进行转义,CDATA节和转义字符都能实现原样输出,优先选择CDATA 6.处理指令 processing instruction 控制xml文档如何被解析引擎所解析的。控制xml数据的显示样式 <?xml-stylesheet type="text/css" href="css.css"?> XSLT可以实现对xml的显示控制 xml应用 1.存储和数据传输 为了方便,不使用xml约束技术 所有xml的生成和解析都是通过程序完成 2.配置文件,为了保证元素的准确性,使用约束技术 --------------------------------------------------------------------------- 为什么使用xml约束? 使用xml约束,可以使元素内容更加规范。如果企业开发中没有使用约束,是因为使生成和解析xml的过程更加简单 DTD Document Type Definition 语法 <!ELEMENT element name> 每个元素对应一个element xml文档 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE books SYSTEM "books.dtd"> <books> <book> <name>java编程思想</name> <price>108</price> </book> </books> dtd约束文档 <?xml version="1.0" encoding="UTF-8"?> <!ELEMENT books (book)> <!ELEMENT book (name,price)> <!ELEMENT name (#PCDATA)> <!ELEMENT price (#PCDATA)> DTD约束可以作为一个单独的文件编写,也可以在xml文档内部编写 DTD与xml文档关联的三种方式 1.内部DTD <!DOCTYPE 根元素 [..]> <!DOCTYPE books [ <!ELEMENT books (book)> <!ELEMENT book (name, price)> <!ELEMENT name (#PCDATA)> <!ELEMENT price (#PCDATA)> ]> 2.外部DTD(引用本地dtd) <!DOCTYPE 根元素 SYSTEM "本地文件地址"> 3.公共DTD(引用网络上的dtd) <!DOCTYPE 根元素 PUBLIC "DTD名称" "DTD文件的URL"> 公共DTD名称 W3C官方组织规定的 元素ELEMENT定义 <!ELEMENT 元素名 (子元素或者元素类型)> ()表示子元素或者分组 ,表示元素的顺序 + * ?表示元素出现的次数,类似正则表达式 |表示多个选一个 元素类型: #PCDATA,EMPTY,ANY,其他类型 属性ATTLIST定义 <!ATTLIST 元素名 属性列表(多个)> 属性列表定义 属性名 类型 约束 常用的三个类型 CDATA 文本类型属性 ID 表示属性值唯一 (1|2|3)多选一 约束 #REQUIRED 属性必须 #IMPLIED 属性可选 #FIXED 属性值固定 Default 默认值 实体ENTITY定义(对于重复的xml数据内容,可以抽取为实体) <!ENTITY 实体名称 "实体值"> 引用实体 &实体名称; --------------------------------------------------------------------------- XML Schema(模式文档) 包含一套预定义的元素和属性(这套元素和属性规定了schema文档的结构和内容), 可以根据这些预定义的元素和属性来编写自己的schema文档,最终用这个schema文档来完成对xml实例的约束 Schema文档本身是XML文档 DTD使用单独的语法 编写了一个XML Schema约束文档后,通常需要把这个文档中定义的元素和属性绑定到一个唯一的URI地址(名称空间)上, XML实例文档通过这个URI告诉解析引擎,文档中包含的元素来自哪里,被谁约束 为什么需要引入名称空间? 一个xml实例可以包含多个schema文档,当多个schema中定义了同名元素,为了区分哪个元素来自哪个schema文档,就有了名称空间的概念 编写一个schma文档的步骤 1. 引入预定义的schema元素和属性的名称空间 xmlns="http://www.w3.org/2001/XMLSchema" 2. 在schema文档中定义自己的元素和属性,最后将这些元素和属性绑定到一个名称空间上,以供xml实例文档引用 targetNamespace="http://www.example.org/books" 3. 在xml实例文档中引入自定义的schema文档 xmlns="http://www.example.org/books" 4. 声明xml实例文档使用了schema文档约束 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 5. 指定引入的自定义schema文档的位置 xsi:schemaLocation="http://www.example.org/books books.xsd"> (格式:名称空间 schema文档位置) books.xsd <?xml version="1.0" encoding="UTF-8"?> <schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/books" elementFormDefault="qualified"> <!-- 每个元素对应一个element --> <element name="books"> <!-- 包含子元素或者属性的元素 表示一个复杂元素 --> <complexType> <!-- sequence强调子元素的顺序 --> <sequence> <element name="book"> <complexType> <sequence> <!-- 简单元素的类型直接通过type属性指定 --> <element name="name" type="string"/> <element name="price" type="double"/> </sequence> </complexType> </element> </sequence> </complexType> </element> </schema> books.xml <?xml version="1.0" encoding="UTF-8"?> <books xmlns="http://www.example.org/books" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.org/books books.xsd"> <book> <name>Core Java</name> <price>222</price> </book> </books> http://www.intertech.com/Blog/xml-schema-elementformdefault-and-attributeformdefault/ elementFormDefault="qualified"(默认值,建议使用) 表示xml实例中的全局元素(schema文档中schema节点的直接节点)和局部元素(非schema节点的直接节点)都必须使用前缀 elementFormDefault="unqualified"(需要给每个引入的名称空间加一个前缀,否则,如果将引入的名称空间作为xml实例文档的默认名称空间, 使用schema文档中定义的局部元素会报错 -- 元素前没有加任何名称空间,表示属于被默认名称空间限定,这与elementFormDefault="unqualified"不符) 表示xml实例中的全局元素使用前缀,局部元素不使用前缀 attributeFormDefault="qualified"(需要给每个引入的名称空间加一个前缀,否则,如果将引入的名称空间作为xml实例文档的默认名称空间, 使用schema文档中定义的属性会报错 -- 属性前没有加任何名称空间,表示属于被不包含任何前缀,这与attributeFormDefault="qualified"不符) 表示xml实例中所有属性必须使用前缀 attributeFormDefault="unqualified"(默认值,建议使用) 表示xml实例中所有属性都不使用前缀 ------------------------------------------------------ XML解析:DOM和SAX DOM:Document Object Model(文档对象模型) 思想:将整个XML文档加载到内存中(所有的元素、属性、文本、注释、CDATA、XML文档都会被解析成一个Node对象),形成一个文档对象(树形结构), 所有对XML的操作都基于这个内存中的文档对象 W3C组织推荐的标准 -- 所有开发语言都支持 SAX:Simple API for XML (XML简单API) 非推荐标准,来自XML社区 思想:不需要将整个XML文档加载到内存中,边解析,边处理,处理完成后释放相应的内存资源 STAX:The Stream API for XML(XML流式API)从JDK1.6新加入的 STAX是一种拉模式的XML处理方式,而SAX是一种推模式的XML处理方式 推模式(push):由服务器为主导,主动向客户端发送数据 拉模式(pull): 由客户端为主导,主导向服务器申请数据 XML解析方式:解析XML的思想 XML解析开发包:解析XML思想的具体实现 常用的XML解析开发包: JAXP(Java API for XML Processing)SUN公司实现的XML解析包,支持DOM、SAX、STAX DOM4j 来自开源社区的XML解析的开源框架,支持DOM XML PULL Java开源框架中的一种XML解析实现(Android内置了pull解析器),支持STAX 当SAX或STAX解析XML文档时,如果读到内存的数据不被释放,那么内存中将包含整个XML文档的数据(类型DOM 支持修改和回写) javaee开发中,优先选择DOM方式(编程简单)解析XML,如果XML文档非常大,优先考虑使用STAX方式解析XML 移动开发中优先使用STAX方式解析XML文档 javax.xml.parsers:dom、sax解析相关的解析器和工厂类 javax.xml.stream:stax解析相关的类 org.w3c.dom:dom解析相关的类(数据节点类) org.xml.sax:sax解析相关的类 ---------------------------------------------------------- DOM解析 1、产生dom解析器工厂 2、通过dom解析器工厂生成dom解析器 3、通过dom解析器解析xml文档,返回代表整个xml文档的document对象 4、通过document对象完成对xml文档的各种操作 Node接口:当xml文档加载到内存后,所有的数据都是一个节点(元素节点Element,属性节点Attr,文本节点Text,注释节点,CDATA节点,文档节点Document...) 所有的这些节点都是node接口的子接口 Node接口的三个通用方法: getNodeName():返回节点的名称 getNodeType():返回节点的类型 getNodeValue():返回节点的值 ---- 所有元素节点value都是 null <name>xxx</name> 获得name元素内容xxx的两种方法 1、node.getFirstChild().getNodeValue() 先获取name元素的第一个子节点getFirstChild(),然后获取节点的内容getNodeValue() 2、node.getTextContent() 直接获取name元素的文本节点的内容 关于节点查找,常用的几个方法 node.getChildNodes() 获得当前节点下面所有子节点 node.getFirstChild() 获得当前节点的第一个子节点 node.getLastChild() 获得当前节点的最后一个子节点 node.getParentNode() 获得当前节点的父节点 node.getPreviousSibling() 获得当前节点的前一个兄弟节点 node.getNextSibling() 获得当前节点的下一个兄弟节点 book元素包含多少个子节点?(5个,三个文本节点,两个元素节点) <book id="b0001"> <name>java编程思想</name> <price>119</price> </book> document.getElementById() 只有在使用了约束的xml文档中,才起作用 一般情况都使用document.getElementsByTagName() 所有开发语言中都默认支持DTD,如果需要使用schema,需要单独编程导入schema <!DOCTYPE books [ <!ELEMENT books (book+)> <!ELEMENT book (name, price)> <!ELEMENT name (#PCDATA)> <!ELEMENT price (#PCDATA)> <!ATTLIST book id ID #REQUIRED> ]> <books> <book id="b0001"> <name>java编程思想</name> <price>119</price> </book> <book id="b0002"> <name>java分布式计算</name> <price>85</price> </book> </books> document.getDocumentElement() 获得文档根节点 document.createElement 创建一个新的节点 node.appendChild() 在node节点的最后追加一个子节点 parentNode.removeChild(node) 删除node节点 删除节点: NodeList nodeList = doc.getElementsByTagName("name"); for (int i = 0; i < nodeList.getLength(); i++) { System.out.println(nodeList.getLength()); Element name = (Element) nodeList.item(i); if (name.getTextContent().contains("java")) { Node book = name.getParentNode(); book.getParentNode().removeChild(book); i--; //删除节点后,总的节点数减1,i减1 } } --------------------------------------------- SAX解析 (基于事件驱动) 原理:将待解析的xml文档和事件处理器传递给sax解析器,sax解析器逐行处理xml文档,扫描到文档开始、结束,元素开始、结束,文本内容等地方时会回调 事件处理器中的事件方法,直至解析完整个xml文档 五个常用的事件处理方法: startDocument() 文档开始事件 startElemen() 元素开始事件 characters() 文本元素事件 endElement() 元素结束事件 endDocument() 文档结束事件 为什么说SAX是推模式解析? 解析器控制xml文档解析,由解析器调用相应事件方法 在startElemen() endElement() 获得开始和结束元素名称 在characters() 获得读取到文本内容 在startElemen() 读取属性值 -------------------------------------------- PULL解析(使用STAX方式解析,拉模式) 原理:将xml文档传递给解析器,在客户端手动通过next()获取当前事件(类型),执行相应的事件处理 STAX解析方式比SAX高校? 1、SAX处理所有的事件类型,STAX由客户端控制要处理的事件类型 2、STAX可以随时终止解析过程