标记语言概述
标记语言,是一种将文本(Text)以及文本相关的其他信息结合起来,展现出关于文档结构和数据处理细节的电脑文字编码。一部分是标记,一部分是标记中的内容,两部分构成标记语言 <标记>..内容..</>格式.
当今广泛使用的标记语言是超文本标记语言,可扩展标记语言标记语言广泛应用于网页和网络应用程序。
1. 超文本标记语言HTML(Hyper Text Markup Language)
Html是标记语言的一种,是典型的标记语言。标记用来对内容进行定义和修饰,内容是数据的本质。普通的标记语言-->Html中用到的所有标记都是事先制定好的,自己不能增加标记定义,只能用已经定义好的标记。 (如 <a></a>表示超链接)
2. 可扩展的标记语言XML(eXtensible Markup Language)
可扩展的标记语言-->可以自己定义标记并赋予意义。
XML的作用:用于数据存储和数据描述
使用场景
a、利用xml充当配置文件
b、用于不同系统间的数据交换(XML可使用不同系统和平台)
c、利用XML存储一些少量数据(大量数据需要使用数据库)
3. Xml和Html语言由同一种父语言SGML(Standard Generalized Markup Language,标准通用标记语言)发展出来的两种语言。
4. 解析器 解析器(比如:XML SPY与用于解析XML文件) ,浏览器 ,MyEclipse
5. W3C(World Wide Web Consortium)
W3C: 开源的语言协会,万维网联盟(World Wide Web Consortium)
HTML和XML都是W3C制定的语言规则
官网:www.w3.org
学习网站:http://www.w3school.com.cn/
XML语法规则
XML文件扩展名为.xml;XML文件由第一行指令和元素构成
指令
XML声明,负责指定xml文件的编码和xml版本。写在XML的第一行<?xml version="1.0" encoding="UTF-8"?> 不要修改。version:语法的版本号 encoding:文字的编码,能写中文
元素(Element)
元素由标记和其中的内容组成 <标记名称>内容</标记名称>
1. 根元素 最外层的元素叫根元素 ,一个XML文件有且只有一个根元素
2. 叶子元素 最里层的(没有子元素的)元素叫叶子元素
3. 空元素 没有内容的元素叫空元素,比如<a></a>,可以简写为:<a /> 。有标记,没内容
4. 普通元素 标记+内容+结束标记
5. 元素必须遵循的语法规则
1)所有的标记都必须有结束 2)开始标记和结束标记必须成对出现 3)元素必须正确嵌套<a><b>c</b></a> (正确) <a><b>c</a></b> (错误) 4)标记的大小写敏感 Hello 和 hello不是同一个标记 5有且只能有一个根元素
标记
标记名字可以随意指定,可以用中文也可以用英文
1. 标记包括开始标记和结束标记 2. 开始标记和结束标记必须成对出现,所有的标记都必须有结束 3. 标记的大小写敏感
注释
格式:<!-- 注释的内容--> 编译器将忽略注释 Html和XML注释方式相同
属性(定义在开始标记中的键值对)
1. 格式:属性="属性值"
2. 要求:属性必须有值,属性值必须用引号引起来,单引号或双引号都可以,但必须一致
3. 属性是隶属于某个元素,<标记名称 属性名=“属性值”>内容</标记内容>,属性可以写多个,属性名不能重复
实体引用(转义字符)
如果元素内容遇到下面几种特殊字符,可以使用实体替代
小于号(<): less than --> < ;
大于号(>): great than --> > ;
And符号(&): &
双引号(“): "
单引号(‘): '
注意这些转义字符都是以&开头,以;结尾的 。<,&字符必须用实体,其他几个建议使用
文本域
格式: < ! [ CDATA [ 文本内容 ] ] > 文本域中的实体引用都被忽略,所有内容被当成一整块文本数据对待
<![CDATA[ 一本好书,没<<笑傲江湖>>好看,比<<Thinking in java>>好看 ]]>
规则小结
1) 必须有唯一的根元素
2) xml标记大小写敏感
3) 标记必须配对出现,有开始有结束
4) 元素必须被正确嵌套
5) 属性必须有值,值必须用引号引括起来
6) 如果遵循所有的规则,称作格式良好的xml文件(well-formed)
使用XML文件描述数据的例子
1. 早期属性文件描述数据的方式
url = jdbc:oracle:thin@192.168.0.26:1521:tarena
dbUser = openlab
dbPwd = open123
2. 现在使用xml表示方式
<datasource id="db_oracle">
<property name="url">jdbc:thin@192.168.0.26:1521:tarena</property>
<property name="dbUser">openlab</property>
<property name="dbPwd">open123</property>
</datasource>
DTD(文档类型定义Document Type Difinition )/Schema
DTD和Schema都是用于限定XML格式的技术。可以限制XML使用那些标记,标记出现顺序,标记嵌套关系,有哪些属性等。有效的xml文件 = 格式良好的xml文件 + 有DTD或Schema规则 + 遵循DTD或Schema的规则
DTD/Schema的由来
行业交换数据时要求xml文件格式相同,所以需要大家遵守规范的xml文件格式。
A学校的XML文件中
<计算机书籍> <书名 isbn="1234">XML的前世今生</书名> <价格>65</价格> <简介>一本好书</简介> <作者>李毅</作者> </计算机书籍>
B学校的XML文件中
<Computer_book> <isbn>1234</isbn> <bookname author="李毅">XML的前世今生</bookname> <price>65</price> <brief>一本好书</brief> </Computer_book>
这两个文件数据相同,但结构不同,无法交换数据
DTD技术
Document Type Definition文本类型定义,可以定义一个XML标记,出现顺序等规则。
1. 定义元素和标记
<!ELEMENT 标记名 (子标记名或#PCDATA)>
定义dept标记,该标记内部可以使用dname和loc子元素
<!ELEMENT dept (dname,loc)>
定义dname标记,该标记只能包含文本内容
<!ELEMENT dname (#PCDATA)>
定义dept标记,该标记内部只能用dname或loc之一
<!ELEMENT dept (dname | loc)>
定义一个loc空元素
<!ELEMENT loc EMPTY>
2. 元素出现次数的定义
*允许出现0到多次. <!ELEMENT depts (dept*)>
+允许出现1到多次.
?允许出现0次或1次
定义package元素,里面可以出现0到多次的interceptors和action,但action必须在interceptors之后
<!ELEMENT package (interceptors*,action*)>
3. 定义属性
<!ATTLIST 标记名 属性 CDATA 默认值>
4. DTD使用方法
在需要限定的XML中,利用下面指定引入。SYSTEM:个人或小范围应用,PUBLIC:某个组织或国际社团使用。浏览器显示的时候,DTD内容不显示
<!DOCTYPE 根元素名 SYSTEM|PUBLIC "dtd文件位置">
5.案例
dept.dtd文件内容
<!ELEMENT DEPTS (DEPT)*> <!ELEMENT DEPT (DNAME,LOC)> <!ELEMENT DNAME (#PCDATA)> <!ELEMENT LOC (#PCDATA)> <!ATTLIST DEPT DEPTNO CDATA #REQUIRED>
dept.xml文件内容
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE DEPTS SYSTEM "depts.dtd"> <DEPTS>
<DEPT DEPTNO="10"> <DNAME>ACCOUNTING</DNAME> <LOC>NEW YORK</LOC> </DEPT> <DEPT DEPTNO="20"> <DNAME>RESEARCH</DNAME> <LOC>DALLAS</LOC> </DEPT>
<DEPT DEPTNO="30"> <DNAME>SALES</DNAME> <LOC>CHICAGO</LOC> </DEPT> </DEPTS>
mybatis的xml配置文件
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="xxx.xx"> ... </mapper>
Schema技术
Schema技术可以实现DTD的定义功能。一个xml只能引用一个DTD,如果引入多个DTD遇到相同标记时会产生混淆。而Schema在引入时需要指定命名空间名,可以通过命名空间名区分。
Java API解析XML文件
Java和xml有很多共同点(比如跨平台、不厂商无关),目前为止java对xml的解析较其他语言更完善
两种解析方式
1. DOM(Document Object Model 文档对象模型)
关键字:树(Document)
优点: 把xml文件在内存中构造树形结构,可以遍历和修改节点
缺点: 如果文件比较大,内存有压力,解析的时间会比较长
2. SAX(Simple API for Xml 基于XML的简单API)
关键字:流(Stream)
把xml文件作为输入流,触发标记开始,内容开始,标记结束等动作
优点: 解析可以立即开始,速度快,没有内存压力
缺点: 不能对节点做修改
JDOM / DOM4J
目前市场上常用的2种解析XML文件的API。dom4j-1.6.1.jar 结合了DOM和SAX两种解析方式的优点
dom4j工具使用步骤
a、引入dom4j.jar开发包
b、利用dom4j提供的API
Document对象:文档树对象
doc.getRootElement()获取树根节点元素
elements("标记名"):获取子节点元素(复数)
element("标记名"):获取子节点元素(单数)
getText():获取节点的文本值
attributeValue("属性名"):获取属性值
setText(val):修改节点文本值
remove(子节点):删除子节点元素
setAttributeValue("属性名","属性值"):修改属性值
addAttributeValue()添加属性值
案例
第一步:引入jar包,pom配置
<!-- dom4j --> <dependency> <groupId>dom4j</groupId> <artifactId>dom4j</artifactId> <version>1.6.1</version> </dependency>
第二步:util工具类
package com.org.qin.common.xml; public class Book { private String id; private String name; private String author; private String price; @Override public String toString() { return this.id + ":" + this.name + ":" + this.author + ":" + this.price; } }
package com.org.qin.common.xml; import java.io.File; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; import org.dom4j.Document; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.dom4j.io.OutputFormat; import org.dom4j.io.SAXReader; import org.dom4j.io.XMLWriter; public class XmlUtil { /** * 生成xml文件 * * @param xmlFile * @param bookList * @throws Exception */ public static void toXMLFlie(String file, List<Book> bookList) throws Exception { Document doc = DocumentHelper.createDocument(); // 创建一个空白的XML文档 Element root = doc.addElement("book-list"); // 添加一个元素,返回值是刚刚添加的元素 for(Book book : bookList){ Element bookElement = root.addElement("book"); bookElement.addElement("id").setText(book.getId()); bookElement.addElement("name").setText(book.getName()); bookElement.addElement("author").setText(book.getAuthor()); bookElement.addElement("price").setText(book.getPrice()); } /** * 这个XML文档存储在内存里, 把XML文档写到文件里,xmlFile * OutputFormat:输出格式 * OutputFormat.createCompactFormat:默认的,紧凑格式,好 * OutputFormat.createPrettyPrint:常写的格式,传入很多空格字符,不好 */ OutputFormat format = OutputFormat.createPrettyPrint(); XMLWriter writer = new XMLWriter(new FileWriter(file), format); writer.write(doc); writer.close(); } /** * 读取xml文件,生成list对象。注意:写这个程序的一定知道XML文档的结构 * * @param xmlFile * @return * @throws Exception */ @SuppressWarnings("unchecked") public static List<Book> parseXmlToBookList(String xmlFile) throws Exception { SAXReader reader = new SAXReader(); // 用于读取XML文档SAXReader Document doc = reader.read(new File(xmlFile)); // Document 用于封装解析后的XML数据 Element root = doc.getRootElement(); // 得到根元素,Element用于封装元素 List<Element> bookElements = root.elements("book");// 返回根元素下名为book的所有节点 List<Book> bookList = new ArrayList<Book>(); for(Element ele : bookElements){ Book book = new Book(); book.setId(ele.element("id").getText()); book.setName(ele.element("name").getText()); book.setAuthor(ele.element("author").getText()); book.setPrice(ele.element("price").getText()); bookList.add(book); } return bookList; } /** * 修改xml文件内容 * * @param xmlFile */ @SuppressWarnings("unchecked") public static void updateXmlText(String xmlFile) throws Exception { SAXReader reader = new SAXReader(); Document doc = reader.read(new File(xmlFile)); Element root = doc.getRootElement(); // 找到根元素books List<Element> bookElements = root.elements("book"); // 从books下找所有的book // 循环找出id=1002的book元素 for(Element ele : bookElements){ String id = ele.element("id").getText(); // 如果是10001删除book节点 if("10001".equals(id)){ root.remove(ele);// 从books节点中将book移除 } // 如果是10002修改price值 else if("10002".equals(id)){ // 定位book的price子元素 Element price = ele.element("price"); // 修改price文本值 price.setText("60"); } } // 将内存中文档树对象状态更新到xml文件中 OutputStream os = new FileOutputStream(xmlFile); XMLWriter writer = new XMLWriter(os); writer.write(doc);// 将doc文档对象输出 writer.flush(); writer.close(); } public static void main(String[] args) throws Exception { List<Book> bookList = new ArrayList<Book>(); // for(int i = 0; i < 5; i++){ // Book book = new Book(); // book.setId("1000" + i); // book.setName("bookName" + i); // book.setAuthor("bookAuthor" + i); // book.setPrice("20.1" + i); // bookList.add(book); // } // 测试生成xml文件 // XmlUtil.toXMLFlie("d:/books.xml", bookList); // 解析xml文件 bookList = XmlUtil.parseXmlToBookList("d:/books.xml"); System.out.println(bookList); // 更新xml文件 XmlUtil.updateXmlText("d:/books.xml"); bookList = XmlUtil.parseXmlToBookList("d:/books.xml"); System.out.println(bookList); } }
XPATH
XPATH:相当于XML的SQL语句,从XML中取出我们想要的数据。功能:可以快速定位文档树对象的节点
在dom4j.jar包基础上引入jaxen-1.1-beta-6.jar,然后利用selectNodes("xpath表达式");selectSingleNode("xpath表达式");
xpath表达式语法:
//节点名 : 定位任意位置的节点元素对象
/节点名 : 定位指定名字的根节点元素
/节点1/节点2 : 定位根节点1下面的节点2
//节点名[子节点名='文本值'] :利用子元素内容做条件定位节点
//节点名[@属性名='属性值'] :利用属性做条件定位节点
public static void main(String[] args) throws Exception { SAXReader reader = new SAXReader(); Document doc = reader.read(new File("d:/books.xml")); List<Element> list = doc.selectNodes("/book-list/book/price"); for(Element e : list){ System.out.println(e.getText()); } list = doc.selectNodes("/book-list/book[price<=200]/price"); for(Element e : list){ System.out.println(e.getText()); } }
“/book-list/book/price":节点路径XPTH,找什么样的节点
Book[ 筛选条件],筛选条件可以有:first() last() postion()==>定哪些元素要哪些元素不要
eg:book[ potion()>1 and postion()<4]:第2,3个元素 Book[ price<200 and price>100]