XML和HTML的比较
全称 | 语法 | 作用 | |
HTML | 超文本标记语言 | 语法松散,标签不区分大小写,标签可以不匹配。 标签是固定的。 | 负责网页的结构 |
XML | Extensible Markup Language 可扩展标记语言 | 语法严格,标签区分大小写,标签须匹配。 标签不固定,可扩展。 | 1)描述带关系的数据结构(作为软件的配置文件,如struts2、hibernate、spring框架、Tomcat服务器) 2)装载数据(作为小型的“数据库”)。 3)应用之间传输数据的格式。另一个流行的格式是JSON。 |
文档声明
在编写XML文档时,需要先使用文档声明,声明XML文档的类型。
最简单的声明语法:
<?xml version="1.0" ?>
用encoding属性说明文档的字符编码:
<?xml version="1.0" encoding="utf-8"?>
用standalone属性说明文档是否独立:
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
注意:xml文件的编码问题:
1)记事本xml文件内容保存的编码(另存为 -> 选择编码 utf-8 保存)
2)解析xml文件内容的编码(<?xml version="1.0" encoding="utf-8"?>)
以上两个编码必须保存一致,才能避免中文乱码问题。
3)如果在ecplise开发工具上编写xml文件,那么xml文件内容会自动按照文档声明的encoding的编码进行保存,所以不会中文乱码问题。
标签
<student>学生</student>
注意:
1)标签一定要配对,可以有空标签(无标签体),空标签简写形式不能省略结束标记斜杠 / 。
2)标签名区分大小写,不能以数字开头,中间不能包含空格,如果没有指定名称空间,不能含有冒号。
3)一个xml文件有且仅有一个根标签。
4)标签可以嵌套但不能交叉。
5)空格和换行也是标签体内容。
属性
<student id="1"></student>
注意:
1)一个属性分为属性名和属性值。属性名和值之间使用=号分割。
2)属性值一定要使用单引号或者双引号包含,不能省略,也不能单双混用!
3)一个标签内可以包含多个属性,但是不能出现同名的属性。
注释
<!-- 注释内容 --->
转义字符
和HTML的转义字符(字符实体)一致。
CDATA块
把CDATA块中的内容全部原样输入。语法:
<![CDATA[
内容
]]>
其他处理指令(processing instruction)
<?xml-stylesheet type="text/css" href="1.css"?>(已过时)
使用该处理指令,可以让xml像html一样使用。(已过时)
XML解析之DOM解析
XML解析方式和解析工具
DOM解析(Document Object Model) | SAX解析(Simple API for XML) | |
原理 | 文件一次性加载进内存,转化为document树,通过树上的对象获取或设置xml文件信息 | 加载一点,读取一点,处理一点。解析XML文档的时候可以触发一系列的事件。 |
优缺点 | 内存占用大(文件太大内存会溢出)。 可以查询和修改。 | 内存占用小。 只能查询。 |
编程方式 | 面向对象方式编程 | 基于事件方式编程 |
应用场景 | 修改或输出xml文件 | 提取部分数据到应用程序 |
解析的工具 | 1)Sun官方jaxp工具 2)jdom工具 3)dom4j工具:三大框架读取xml文件的程序。(非官方的,第三方的) | sun公司官方的sax解析工具,jdk中自带sax解析工具的api: org.xml.sax.*; |
JAXP-DOM示例:
package xml; import java.io.File; import java.io.IOException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; public class JaxpDemo { public static void main(String[] args) { //获取 DocumentBuilderFactory 的新实例。 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); //指定由此代码生成的解析器将忽略注释 dbf.setIgnoringComments(true); //设置忽略空格 dbf.setIgnoringElementContentWhitespace(true); DocumentBuilder db = null; Document document = null; try { //获取DocumentBuilder的实例 db = dbf.newDocumentBuilder(); File file = new File("E:\\contact.xml"); document = db.parse(file); //按文档顺序返回包含在文档中且具有给定标记名称的所有 Element 的 NodeList NodeList nodeList = document.getElementsByTagName("name"); for (int i = 0; i < nodeList.getLength(); i++) { Node node = nodeList.item(i); //输出标记的值 System.out.println(node.getFirstChild().getNodeValue()); } } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } |
dom4j工具使用
dom4j集成Xpath(路径查询语言)支持、XML Schema(约束模式文档)支持。
编程步骤:
1)到dom4j的官方下载 。dom4j-1.6.1.zip
2)导入dom4j的支持jar包、dom4j-1.6.1.jar核心包
3)写代码。
常用API:
获取或创建文档对象:
获取文档对象:Document document = new SAXReader().read("xml文件路径");
创建文档对象:Document document = DocumentHelper.createDocument();
将文档对象写出到xml文件:
1)设置输出格式:
紧凑模式:OutputFormat compactFormat = OutputFormat.createCompactFormat();//紧凑模式,节省带宽,上线时使用
美观模式:OutputFormat prettyPrint = OutputFormat.createPrettyPrint();//美观模式,便于查看,开发时使用
2)设置输出编码(同时设置了文档声明中encoding的值):
outputFormat.setEncoding("utf-8");
3)创建写出器(无 outputFormat 参数则默认使用紧凑模式和UTF-8编码):
XMLWriter xmlWriter = new XMLWriter(new FileOutputStream("要写出的xml文件路径"), outputFormat);
4)写出Document对象到XML文件:
xmlWriter.write(document);
5)关闭资源:
xmlWriter.close();
元素、属性、文本操作
查:
元素:
document.getRootElement(); 获取根标签
element.elements(); 获取所有子标签
element.elements("子元素名"); 获取指定名称的所有子标签
element.element("子元素名"); 获取指定名称的首个子标签
element.getName(); 获取标签名
属性:
element.atrributes(); 获取该标签的所有属性对象
element.atrribute("属性名"); 从标签获取指定属性名的属性对象
element.atrribute(属性索引); 从标签获取指定属性索引的属性对象(属性索引从0开始)
element.atrributeValue("属性名"); 从标签获取指定属性名的属性值
atrribute.getName(); 从属性获取属性名
atrribute.getValue(); 从属性获取属性值
文本:
element.getText(); 获取标签的文本
element.elementText("子元素名"); 获取指定名称的首个子标签的文本
增:
document.addElement("元素名"); 创建元素
element.addAtribute("属性名","属性值"); 创建属性(返回原元素对象)
element.addText("文本内容"); 追加文本
改:
setValue(); 修改属性值
addAttribute("同名属性","修改值"); 修改属性值
setText(); 修改文本
删:
标签/属性.detach(); 自杀
标签/属性.getParent().remove(标签/属性); 他杀
XPath技术
作用
快速查询和修改xml文件的节点。
编程步骤
1)导入dom4j的xpath插件包:jaxen-1.1-beta-6.jar
2)在dom4j中使用xpath:
List<Node> list = selectNodes("xpath表达式"); 查询多个节点(标签/属性/文本)
Node node = selectSingleNode("xpath表达式"); 查询单个节点(标签/属性/文本),如有多个,返回第一个
XPath表达式(重点)
/ 绝对路径 斜杠在最前面,代表xml文件的根。斜杠在中间,表示子元素。
// 相对路径 选择后代元素(不分层次结构)
* 通配 选择所有元素
[ ] 条件 选择什么条件下的元素。例如 /AAA/BBB[1] 选择第一个BBB子元素
@ 属性 选取属性
= 内容 (值)
and 逻辑与
text() 选取文本内容
路径表达式 | 结果 |
bookstore | 选取 bookstore 元素的所有节点 |
/bookstore | 选取根元素 bookstore 注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径! |
bookstore/book | 选取所有属于 bookstore 的子元素的 book 元素。 |
//book | 选取所有 book 子元素,而不管它们在文档中的位置。 |
bookstore//book | 选择所有属于 bookstore 元素的后代的 book 元素,而不管它们位于 bookstore 之下的什么位置。 |
使用限定语[]
路径表达式 | 结果 |
/bookstore/book[1] | 选取属于 bookstore 子元素的第一个 book 元素。 |
/bookstore/book[last()] | 选取属于 bookstore 子元素的最后一个 book 元素。 |
/bookstore/book[last()-1] | 选取属于 bookstore 子元素的倒数第二个 book 元素。 |
/bookstore/book[position()<3] | 选取最前面的两个属于 bookstore 元素的子元素的 book 元素。 |
//title[@lang] | 选取所有拥有名为 lang 的属性的 title 元素。 |
//title[@lang='eng'] | 选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。 |
/bookstore/book[price>35.00] | 选取所有 bookstore 元素的 book 元素,且其中的 price 元素的值须大于 35.00。 |
使用通配符
路径表达式 | 结果 |
/bookstore/* | 选取 bookstore 元素的所有子节点 |
//* | 选取文档中的所有节点 |
//title[@*] | 选取所有带有属性的 title 元素。 |
//book/title | //book/price | 选取所有 book 元素的 tilte 和 price 元素。 |
XML解析之SAX解析
SAX 解析器在解析开始的时候就开始发送事件。当解析器发现文档开始、元素开始和文本等时,代码会收到一个事件。
SAX 解析器根本不创建任何对象,它只是将事件传递给您的应用程序。如果希望基于那些事件创建对象,这将由您来完成。
DefaultHandler类
startElement(): 开始标签
characters():文本内容
endElement(): 结束标签
案例
打印xml文件主要内容
package xml; import java.io.IOException; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; public class SaxDemo_PrintXml { public static void main(String[] args) { SAXParser saxParser; try { saxParser = SAXParserFactory.newInstance().newSAXParser(); saxParser.parse("./src/contact.xml", new PrintXmlHandler()); } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } class PrintXmlHandler extends DefaultHandler { private StringBuffer sb = new StringBuffer(); @Override public void startDocument() throws SAXException { System.out.println("指定XML文件的主要内容为:\r"); } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { sb.append("<" + qName); if (null != attributes) { for (int i = 0; i < attributes.getLength(); i++) { sb.append(" " + attributes.getQName(i) + "=\"" + attributes.getValue(i) + "\""); } } sb.append(">"); } @Override public void characters(char[] ch, int start, int length) throws SAXException { sb.append(new String(ch, start, length)); } @Override public void endElement(String uri, String localName, String qName) throws SAXException { sb.append("<" + qName + ">"); } @Override public void endDocument() throws SAXException { System.out.println(sb); } } |
提取xml内容到对象
package xml; import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; public class SaxDemo_XmlToObject { public static void main(String[] args) { SAXParser saxParser; try { saxParser = SAXParserFactory.newInstance().newSAXParser(); MyDefaultHandler myDefaultHandler = new MyDefaultHandler(); saxParser.parse("./src/contact.xml", myDefaultHandler); List<Contact> conList = myDefaultHandler.getList(); for (Contact contact : conList) { System.out.println(contact); } } catch (ParserConfigurationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SAXException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } class MyDefaultHandler extends DefaultHandler { //用于存储一个contact标签中的信息 private Contact contact = null; //用于存储所有Contact对象信息 private List<Contact> conList = new ArrayList<Contact>(); //用于返回储所有Contact对象信息 public List<Contact> getList() { return conList; } //用于存储当前解析到的元素 private String curTag = null; //用于存储当前解析到的文本 private String curText = null; @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { //供characters方法解析文本之用 curTag = qName; if ("contact".equals(qName)) { contact = new Contact(); contact.setId(attributes.getValue("id")); } } @Override public void characters(char[] ch, int start, int length) throws SAXException { if (null != curTag) { curText = new String(ch, start, length); switch (curTag) { case "name": contact.setName(curText); break; case "gender": contact.setGender(curText); break; case "phone": contact.setPhone(curText); break; case "email": contact.setEmail(curText); break; case "address": contact.setAddress(curText); } } } @Override public void endElement(String uri, String localName, String qName) throws SAXException { //供characters方法丢弃空白及换行文本之用 curTag = null; if ("contact".equals(qName)) { conList.add(contact); } } } class Contact { private String id; private String name; private String gender; private String phone; private String email; private String address; @Override public String toString() { return "Contact [id=" + id + ", name=" + name + ", gender=" + gender + ", phone=" + phone + ", email=" + email + ", address=" + address + "]"; } 省略getter和setter方法 } |
其他XML解析工具
Xstream
<dependency> <groupId>com.thoughtworks.xstream</groupId> <artifactId>xstream</artifactId> <version>1.4.10</version> </dependency> |
XML约束(看懂即可)
什么是约束?
xml语法: w3c组织对xml文件的编程规则规范。(w3c组织制定的)
xml约束: 由开发者指定的对xml文件内容规范。(开发者根据业务指定的)
约束分类
DTD约束:相对简单,数据类型简单。 场景:Hibernate Struts2
Schema约束:相对复杂,功能强大,数据类型非常丰富。 场景:Spring
DTD约束
1)dtd的使用方法
内部的dtd:约束内容写在xml文件中。
外部的dtd:约束内容写在另一个文件中,在xml中引用。
2)语法
约束标签
<!ELEMENT 元素名称 类别> 或 <!ELEMENT 元素名称 (元素内容)>
类别:
EMPTY:空标签
PCDATA:普通字符串(不能包含子标签)
ANY: 任意内容(空标签/字符串/可以包含子标签)
顺序问题:
(子元素名称 1,子元素名称 2,.....): 一定要依次出现1,2,...
数量问题:
子元素: 有且仅有1个
+ : 1个或多个
* : 0个或多个
? : 0个或1个
约束属性
<!ATTLIST 元素名称 属性名称 属性类型 默认值>
默认值:
#REQUIRED:必须
#IMPLIED:不是必须的
#FIXED value : 固定的
属性类型:控制属性值
CDATA:普通字符串
(en1|en2...): 枚举中的一个值
ID: 唯一的值
Schema约束
重点:名称空间(知道如何依据名称空间找到scheme约束文件,语法查询w3c文档)