版权声明:如果你觉得还可以的,转载请联系。 https://blog.csdn.net/u011974639/article/details/52985056
xml介绍
文档说明
一个良好的xml文件,需要对xml文件有一个基本的介绍和基础属性的设置.最基本的文档说明如下:
- <?xml version="1.0" ?>
常见的文档说明如下
- <?xml version="1.0" encoding="UTF-8" standalone="no"?>
- <!-- version:声明版本号
- encoding:指定编码格式,例如 gb2312 utf-8 注意在编写文件中存取和读取的编码需一致
- standalone:文档是否独立 -->
元素(element)
声明格式:以下两种xml声明格式
- <!-- 声明格式1 --> <a id="9527">...</a> <!-- 常常把一个元素称为一个标签 -->
- <!-- 声明格式2 --> <a id="9527"/> <!--此声明格式不含子标签 --></span>
xml元素需要注意一些规范
1.大小写区分,不能包含空格,不能有;号
2.不要以_开头,也不要以xml开头
注意:在xml文件中空格和换行都算是text内容,会被程序解析(红刷笔刷过的地方)
demo
- <?xml version="1.0" encoding="UTF-8" standalone="no"?>
- <exam> <!-- 根节点为exam -->
- <student id="1" > <!-- 子标签student 包含一个属性id -->
- <name>xiaosan</name> <!-- 子标签name,location,grade-->
- <location>沈阳</location>
- <grade>89</grade>
- </student>
- <student id="2" >
- <name>xiaowu</name>
- <location>合肥</location>
- <grade>29</grade>
- </student>
- </exam>
特殊语法
使用<![CDATA[ .... ]]>告诉解析器不解析内含字段,原样输出。
- <![CDATA[
- <student id="1" > <!-- 子标签student 包含一个属性id -->
- <name>xiaosan</name> <!-- 子标签name,location,grade-->
- <location>沈阳</location>
- <grade>89</grade>
- </student>
- ]]>
一些特殊字段使用转义字符来表示
xml约束
所谓的约束,即编写xml文件的指导说明。常用的xml约束有两种:DTD和Schema.DTD语法简单但是对属性类型具有局限性,Schema相对更为严谨也更为复杂,两者都有成熟的文档,可以参考文档编写,一般能看懂即可。
DTD约束
DTD可以直接在相应的xml文档中声明,也可以单独为一个dtd文件。
1.直接在xml文件中定义
- <?xml version="1.0" encoding="UTF-8"?>
- <!--
- 内部DTD声明 ,格式为:
- <!DOCTYPE root_name root_name为xml文件的根节点
- [
- ....
- ]
- >
- -->
- <!DOCTYPE person[
- <!ELEMENT person (人+)>
- <!ELEMENT 人 (姓名+,年龄,(住址*|家乡?))>
- <!ELEMENT 姓名 (#PCDATA)>
- <!ELEMENT 年龄 (#PCDATA)>
- <!ELEMENT 住址 (#PCDATA)>
- ]>
- <person>
- <人>
- <姓名>小李</姓名>
- <年龄>23</年龄>
- <住址>岗头村</住址>
- </人>
- <人>
- <姓名>小王</姓名>
- <姓名>隔壁老王</姓名>
- <年龄>30</年龄>
- <家乡>二八村</家乡>
- </人>
- </person>
2.单独编写一个DTD文件
person.dtd文件
- <?xml version="1.0" encoding="UTF-8"?>
- <!ELEMENT person (人+)>
- <!ELEMENT 人 (姓名+,年龄,(住址*|家乡?))>
- <!ELEMENT 姓名 (#PCDATA)>
- <!ELEMENT 年龄 (#PCDATA)>
- <!ELEMENT 住址 (#PCDATA)>
- <?xml version="1.0" encoding="UTF-8"?>
- <!--
- 使用外部声明的DTD ,需要加入:
- <!DOCTYPE 根元素名称 SYSTEM/PUBLIC "外部文档名称或路径.dtd" >
- -->
- <<!DOCTYPE person PUBLIC SYSTEM "person.dtd">
- <person>
- <人>
- <姓名>小李</姓名>
- <年龄>23</年龄>
- <住址>岗头村</住址>
- </人>
- <人>
- <姓名>小王</姓名>
- <姓名>隔壁老王</姓名>
- <年龄>30</年龄>
- <家乡>二八村</家乡>
- </人>
- </person>
DTD语法简介
- <?xml version="1.0" encoding="UTF-8"?>
- <!ELEMENT person (人+)>
- <!ELEMENT 人 (姓名+,年龄,(住址*|家乡?))>
- <!ELEMENT 姓名 (原名|昵称)>
- <!ATTLIST 原名
- 中文名 CDATA #REQUIRED
- 英文名 CDATA #IMPLIED
- 阿三名 CDATA #FIXED "乌拉拉"
- >
- <!ATTLIST 昵称
- QQ昵称 (xiao|li|wang) "sb"
- >
- <!ELEMENT 年龄 (#PCDATA)>
- <!ELEMENT 住址 (#PCDATA)>
- <!--
- 元素内容使用,号表示出现次序需要一致
- 元素内容使用|号表示只能选择其一
- 元素中使用+、?、*表示元素出现次数
- ? 0次或1次 (人?)
- + 1次或多次 (人+)
- * 0次或多次 (人*)
- 对于标签可以使用ATTLIST为其设置属性
- <!ATTLIST 元素名
- 属性1 类型 设置说明
- 属性2 ... ...
- ...
- >
- 常见类型:
- cdata 为常见字符串
- (?|?|?) 给定范围取值
- id 表示唯一属性
- entity 表示一个实体(类似一个宏定义)
- ...
- 设置说明:
- #REQUIRED 必须有此属性
- #IMPLIED 可有
- #FIXED 固定值
- "xxx" 如果没表定,则默认值
- -->
schema语法
因为schema的语法和xml语法类似。
一个schema文档必须有一个根节点,且根节点名称为schema。每个schema模式文档可以声明一个名称空间,同时用一个唯一的URI表示。
在schema文件中
schema.xsd文档声明
- <!--根元素schema。
- 使用xmlns关键字引入命名空间xs
- 同时限定该文档的约束对象URI:www.delphifan.com
- -->
- <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
- targetNamespace="http://www.delphifan.com" elementFormDefault="qualified">
对于的xml文件中
- <!-- xmlns="http://www.delphifan.com" -> 使用默认命名空间
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" -> 使用xsi命名空间 配置 xsi:schemaLocation属性
- xsi:schemaLocation="http://www.delphifan.com shiporder.xsd" -> 声明该文档的约束文档的URI和对于的文档名称
- -->
- <shiporder
- xmlns="http://www.delphifan.com"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.delphifan.com shiporder.xsd"
- orderid="23" >
注意: 在声明xsi:schemaLocation属性时候按照xsi:xsi:schemaLocation="{namespace} {location}" 格式声明。namespace和location之间的空格不能少。
demo
shiporder.xsd约束文档
- <?xml version="1.0" encoding="UTF-8"?>
- <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
- targetNamespace="http://www.delphifan.com" elementFormDefault="qualified">
- <xs:element name="shiporder">
- <xs:complexType> <!--complexType表示一个复杂类型 -->
- <xs:sequence> <!--xs:sequence表示元素值必须按顺序声明 -->
- <xs:element name="orderperson" type="xs:string" />
- <xs:element name="shipto">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="name" type="xs:string" />
- <xs:element name="address" type="xs:string" />
- <xs:element name="city" type="xs:string" />
- <xs:element name="country" type="xs:string" />
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="item" maxOccurs="unbounded">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="title" type="xs:string" />
- <xs:element name="note" type="xs:string" minOccurs="0" />
- <xs:element name="quantity" type="xs:positiveInteger" />
- <xs:element name="price" type="xs:decimal" />
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attribute name="orderid" type="xs:string" use="required" />
- </xs:complexType>
- </xs:element>
- </xs:schema>
shiporder.xml文档
- <?xml version="1.0" encoding="UTF-8"?>
- <shiporder
- xmlns="http://www.delphifan.com"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.delphifan.com shiporder.xsd"
- orderid="23" >
- <orderperson>fan</orderperson>
- <shipto>
- <name>xiaofan</name>
- <address>hefei</address>
- <city>anhui</city>
- <country>zhongguo</country>
- </shipto>
- <item>
- <title>schema technology</title>
- <note>so handsome</note>
- <quantity>23</quantity>
- <price>12.2</price>
- </item>
- </shiporder>
xml解析
解析方式分为两种:dom和sax
dom(document object model )解析:
一次性读取xml文件,可对xml里数据操作。 优点CRUD操作方便,但占用内存大
sax(simple API for XML)解析:
一点一点读取。优点是占用内存小,速度快,但CRUD操作不方便
常用的xml解析开发包
jaxp(官方的不需要外部jar包)与dom4j(需要外部jar包)
DOM解析(jaxp包)
整体流程如图所示
过程大致分为两部分
1.修改部分
使用DocumentBuilderFactory产生factory对象-->产生DocumentBuilder对象 -->使用parse()方法得到ducment对象
对document对象可以获取指定元素,作CRUD操作等
2.保存部分
使用TransformerFactory-->得到factory对象-->得到Transformer()对象-->使用transform()方法把改变后的document对象存储至xml文件中
demo
任务需求:要求编写一个工具类
1.直接操作Student对象在xml文件中存储
2.在xml文件中通过examid属性查找对应的student标签
3.通过name属性在xml文件中删除对于的student标签
设计思路如下图
1.studentDao负责对xml文件操作,包含三个方法,即增加学生对象,删除,查找操作
2.因为对xml操作中有大量重复代码,故定义工具类简化操作
student类
- package org.nihao.domain;
- public class Student {
- private int idcard;
- private int examid;
- private String name;
- private String location;
- private double score;
- public int getIdcard() {
- return idcard;
- }
- public void setIdcard(int idcard) {
- this.idcard = idcard;
- }
- public int getExamid() {
- return examid;
- }
- public void setExamid(int examid) {
- this.examid = examid;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public String getLocation() {
- return location;
- }
- public void setLocation(String location) {
- this.location = location;
- }
- public double getScore() {
- return score;
- }
- public void setScore(double score) {
- this.score = score;
- }
- }
studentDao.java
- package org.nihao.dao;
- import org.nihao.domain.Student;
- import org.nihao.exception.StudentNotExistException;
- import org.nihao.util.XmlUtils;
- import org.w3c.dom.Document;
- import org.w3c.dom.Element;
- import org.w3c.dom.NamedNodeMap;
- import org.w3c.dom.Node;
- import org.w3c.dom.NodeList;
- public class StudentDao {
- public void add(Student s){
- try {
- Document document = XmlUtils.getDocument(); //checked exception
- //1.创建标签
- Element element = document.createElement("student");
- //创建子标签并填充子标签
- Element nameElement = document.createElement("name");
- nameElement.setTextContent(s.getName());
- Element locationElement = document.createElement("location");
- locationElement.setTextContent(s.getLocation());
- Element gradeElement = document.createElement("grade");
- gradeElement.setTextContent(Double.toString(s.getScore()));
- //2.填充数据
- element.setAttribute("idcard", Integer.toString(s.getIdcard()));
- element.setAttribute("examid", Integer.toString(s.getExamid()));
- element.appendChild(nameElement);
- element.appendChild(locationElement);
- element.appendChild(gradeElement);
- document.getElementsByTagName("exam").item(0).appendChild(element);
- //3.保存标签
- XmlUtils.write2Xml(document);
- } catch (Exception e) {
- throw new RuntimeException(e); //运行时的异常
- }
- }
- public Student find(int examid){
- try {
- Document document = XmlUtils.getDocument();
- NodeList list = document.getElementsByTagName("student");
- for (int i = 0; i < list.getLength(); i++) {
- Element student = (Element) list.item(i);
- String attribute = student.getAttribute("examid");
- if (attribute.equals(Integer.toString(examid))) {
- Student stu = new Student();
- stu.setExamid(examid);
- stu.setIdcard(Integer.parseInt(student.getAttribute("idcard").trim()));
- stu.setLocation(
- student.getElementsByTagName("location").item(0).getTextContent());
- stu.setName(
- student.getElementsByTagName("name").item(0).getTextContent());
- stu.setScore(Double.parseDouble(student.getElementsByTagName("grade")
- .item(0).getTextContent()));
- return stu;
- }
- }
- return null;
- } catch (Exception e) {
- throw new RuntimeException(e); //运行时的异常
- }
- }
- public void delete(String name) throws StudentNotExistException{
- try {
- Document document = XmlUtils.getDocument();
- NodeList list = document.getElementsByTagName("name");
- for (int i = 0; i < list.getLength(); i++) {
- if (list.item(i).getTextContent().equals(name)) {
- list.item(i).getParentNode().getParentNode()
- .removeChild(list.item(i).getParentNode());
- XmlUtils.write2Xml(document);
- return;
- }
- }
- throw new StudentNotExistException(name+"不存在!"); //自定义异常,用于通知调用者未查找到学生信息
- }catch(StudentNotExistException e){
- throw e;
- }catch (Exception e ) {
- throw new RuntimeException(e); //运行时的异常
- }
- }
- }
XmlUtils.java
- package org.nihao.util;
- import javax.xml.parsers.DocumentBuilder;
- import javax.xml.parsers.DocumentBuilderFactory;
- import javax.xml.transform.Transformer;
- import javax.xml.transform.TransformerException;
- import javax.xml.transform.TransformerFactory;
- import javax.xml.transform.dom.DOMSource;
- import javax.xml.transform.stream.StreamResult;
- import org.w3c.dom.Document;
- public class XmlUtils {
- private static String filename = "src/exam.xml";
- public static Document getDocument() throws Exception {
- DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
- DocumentBuilder documentBuilder = factory.newDocumentBuilder();
- return documentBuilder.parse(filename);
- }
- public static void write2Xml(Document document) throws TransformerException{
- TransformerFactory factory = TransformerFactory.newInstance();
- Transformer transformer = factory.newTransformer();
- transformer.transform(new DOMSource(document), new StreamResult(filename));
- }
- }
exam.xml
- <?xml version="1.0" encoding="UTF-8" standalone="no"?>
- <exam>
- <student id="1" >
- <name>xiaosan</name>
- <location>沈阳</location>
- <grade>89</grade>
- </student>
- <student id="2" >
- <name>xiaowu</name>
- <location>合肥</location>
- <grade>29</grade>
- </student>
- </exam>
sax解析
采用事件处理的方式解析xml文件,分为两个部分:解析器和事件处理器
解析过程如下图
解析器:通过JAXP的api直接创建
事件处理器:
每当解析到一个组成部分,就会调用事件处理器的一个方法,同时会把解析出来的内容作为方法参数传递。
新建一个对象实现给定的ContentHandler,并实现其中方法,重写常用的三个方法startElement、endElement、characters方法
或者使用官方帮我们实现了几个常用的类 DefaultHandler,DefaultHandler2, ValidatorHandler, XMLFilterImpl, XMLReaderAdapter
demo
- public class Demo1 {
- public static void main(String[] args) throws Exception {
- //1.通过工厂得到解析器
- SAXParserFactory factory = SAXParserFactory.newInstance();
- SAXParser parser = factory.newSAXParser();
- //2.通过解析器得到Reader
- XMLReader xmlReader = parser.getXMLReader();
- //设置内容处理器
- xmlReader.setContentHandler(new handler());
- //3.解析
- xmlReader.parse("src/book.xml");
- }
- }
- class handler implements ContentHandler{
- @Override
- public void setDocumentLocator(Locator locator) {
- }
- @Override
- public void startDocument() throws SAXException {
- }
- @Override
- public void endDocument() throws SAXException {
- }
- @Override
- public void startPrefixMapping(String prefix, String uri)
- throws SAXException {
- }
- @Override
- public void endPrefixMapping(String prefix) throws SAXException {
- }
- @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 {
- System.out.println(new String(ch,start,length));
- }
- @Override
- public void ignorableWhitespace(char[] ch, int start, int length)
- throws SAXException {
- }
- @Override
- public void processingInstruction(String target, String data)
- throws SAXException {
- }
- @Override
- public void skippedEntity(String name) throws SAXException {
- }
- }
使用dom4j对xml操作
dom4j的说明文档非常详细,其中包含强大的xpath正则表达式获取元素方法。这里只贴一些简单的demo,需要使用dom4j之间查看其官方的文档即可。
ADU操作
- public void add() throws Exception{
- SAXReader reader = new SAXReader();
- Document document = reader.read(new File("src/book.xml"));
- Element book = document.getRootElement().element("书");
- List elements = book.elements();
- Element element = DocumentHelper.createElement("售价");
- element.setText("200yuan");
- elements.add(2, element);
- //修改完毕后,输出存储
- OutputFormat format = OutputFormat.createPrettyPrint();
- format.setEncoding("UTF-8");
- XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"),format);
- writer.write(document);
- writer.close();
- }
- public void delete() throws Exception{
- SAXReader reader = new SAXReader();
- Document document = reader.read(new File("src/book.xml"));
- Element book = document.getRootElement().element("书");
- book.remove(book.element("售价"));
- OutputFormat format = OutputFormat.createPrettyPrint();
- format.setEncoding("UTF-8");
- XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"),format);
- writer.write(document);
- writer.close();
- }
- public void update() throws Exception{
- SAXReader reader = new SAXReader();
- Document document = reader.read(new File("src/book.xml"));
- Element book = (Element) document.getRootElement().elements("书").get(1);
- book.element("售价").setText("2999元");
- OutputFormat format = OutputFormat.createPrettyPrint();
- format.setEncoding("UTF-8");
- XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"),format);
- writer.write(document);
- writer.close();
- <pre name="code" class="java"> }
- public class Demo3 {
- //基本的XPATH操作
- public void xpath() throws Exception{
- SAXReader reader = new SAXReader();
- Document document = reader.read(new File("src/book.xml"));
- String text = document.selectSingleNode("//作者").getText();
- System.out.println(text);
- }
- }
schema语法
因为schema的语法和xml语法类似,且对类型的限制远好于DTD的类型限制,故schema的使用会更加广泛。
文档后缀名:xxx.xsd 一个schema文档必须有一个根节点,且根节点名称为schema 。每个schema模式文档可以声明一个名称空间,同时用一个唯一的URI表示。
在schema文件中
schema文档的头元素声明
- <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 根元素schema。 使用xmlns关键字引入命名空间xs 同时限定该文档的约束对象URI:www.delphifan.com
- targetNamespace="http://www.delphifan.com" elementFormDefault="qualified">
对于的xml文件中
- <?xml version="1.0" encoding="UTF-8"?>
- <shiporder
- xmlns="http://www.delphifan.com" 使用默认命名空间
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 使用xsi命名空间 并声明该文档的约束文档的URI和对于的文档名称
- xsi:schemaLocation="http://www.delphifan.com shiporder.xsd"
- orderid="23" >
具体的细节可以参考schema官方文档。
demo
shiporder.xsd约束文档
- <?xml version="1.0" encoding="UTF-8"?>
- <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
- targetNamespace="http://www.delphifan.com" elementFormDefault="qualified">
- <xs:element name="shiporder">
- <xs:complexType> <!--complexType表示一个复杂类型 -->
- <xs:sequence> <!--xs:sequence表示元素值必须按顺序声明 -->
- <xs:element name="orderperson" type="xs:string" />
- <xs:element name="shipto">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="name" type="xs:string" />
- <xs:element name="address" type="xs:string" />
- <xs:element name="city" type="xs:string" />
- <xs:element name="country" type="xs:string" />
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="item" maxOccurs="unbounded">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="title" type="xs:string" />
- <xs:element name="note" type="xs:string" minOccurs="0" />
- <xs:element name="quantity" type="xs:positiveInteger" />
- <xs:element name="price" type="xs:decimal" />
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attribute name="orderid" type="xs:string" use="required" />
- </xs:complexType>
- </xs:element>
- </xs:schema>
shiporder.xml文档
- <?xml version="1.0" encoding="UTF-8"?>
- <shiporder
- xmlns="http://www.delphifan.com"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.delphifan.com shiporder.xsd"
- orderid="23" >
- <orderperson>fan</orderperson>
- <shipto>
- <name>xiaofan</name>
- <address>hefei</address>
- <city>anhui</city>
- <country>zhongguo</country>
- </shipto>
- <item>
- <title>schema technology</title>
- <note>so handsome</note>
- <quantity>23</quantity>
- <price>12.2</price>
- </item>