XML技术学习

来源:互联网 发布:考研五战 知乎 编辑:程序博客网 时间:2024/06/05 11:50


XML学习

首先要建立XML文件

之后解析XML文件,主要分这么两部分。

XML语法:

文档声明

元素

属性(附加信息的描述)

注释(不能随意嵌套)

CDATA区、特殊字符

处理指令

文档声明:在编写XML文档时,需要先适用文档声明,声明XML文档的类型。最简单的声明语法<?xml version="1.0" ?>

encoding属性说明文档的字符编码

<?xml version=1.0 encoding=GB2312>

standalone属性说明文档是否独立

<?xml version=1.0 encoding=GB2312standalone=yes>

元素:

XML元素指的是XML文件中出现的标签,一个标签分为开始标签和结束标签,一个标签有。严格对应,区分大小写。

如下几种书写形式:包含标签体<a>www.baidu.com</a>

不包含标签体<a></a> ,<a/>

标签可以嵌套,但不允许交叉嵌套

一个XML文档必须有且仅有一个根标签,其他标签都是它的子孙标签。

对于XML标签中出现的所有空格和换行,XML解析程序都会当作标签内容进行处理。例如:下面两段内容的意义是不一样的。

第一段:

 

<网址>www.itcast.cn</网址>

第二段:

<网址>

www.itcast.cn

</网址>

由于在XML中,空格和换行都作为原始内容被处理,所以,在编写XML文件时,使用换行和缩进等方式来让原文件中的内容清晰可读的“良好”书写习惯可能要被迫改变。

一个XML元素可以包含字母、数字以及其它一些可见字符,但必须遵守下面的一些规范:

区分大小写,例如,<P>和<p>是两个不同的标记。

不能以数字或"_" (下划线)开头。

不能以xml(或XML、或Xml 等)开头。

不能包含空格。

名称中间不能包含冒号(:)。

可以使用中文字符。

属性:

一个标签可以有多个属性,每个属性都有它自己的名称和取值,例如:

<input name=“text”/>

属性值一定要用双引号(")或单引号(')引起来

定义属性必须遵循与标签相同的命名规范

多学一招:在XML技术中,标签属性所代表的信息,也可以被改成用子元素的形式来描述,例如:

<input>

 <name>text</name>

</input>

 

注释:

Xml文件中的注释采用:“<!--注释-->” 格式。

注意:

XML声明之前不能有注释

注释不能嵌套,例如:

<!--大段注释

……

<!--局部注释-->

……

-->

CDATA区/段

在编写XML文件时,有些内容可能不想让解析引擎解析执行,而是当作原始内容处理。

遇到此种情况,可以把这些内容放在CDATA区里,对于CDATA区域内的内容,XML解析程序不会处理,而是直接原封不动的输出。

语法:<![CDATA[  内容   ]]>

<![CDATA[

<itcast>

<br/>

</itcast>

]]>

 

 

转义字符:

&lt; 

 

 

小于号 

&gt; 

 

 

大于号 

&amp; 

& 

 

&apos; 

' 

单引号 

&quot; 

" 

双引号

 

处理指令:1)可以使用css装饰XML文件中的内容2css目前版本只支持英文标签

处理指令,简称PI (processing instruction)。处理指令用来指挥XML解析引擎如何解析XML文档内容。

 

例如,在XML文档中可以使用xml-stylesheet指令,通知XML解析引擎,应用css文件显示xml文档内容。<?xml-stylesheet type="text/css" href=“a.css"?>

 

处理指令必须以“<?”作为开头,以“?>”作为结尾,XML声明语句就是最常见的一种处理指令。

XML约束

XML约束概述

XML技术里,可以编写一个文档来约束一个XML文档的书写规范,这称之为XML约束。为什么需要XML约束?

常用的约束技术

XML DTD(易学,功能有限)

XML Schema (难学,功能强大)

XML DTD约束快速入门

DTD(Document Type Definition),全称为文档类型定义。

浏览器对XML和DTD会进行语法的检测,并没有作约束检测

DTD约束即可以作为一个单独的文件(通过外联)编写,也可以在XML文件内(内嵌)编写。

class.dtd如下:

 

此种方式是作为一个单独的文件:

 

内嵌模式:

 

 

 

XML文件使用 DOCTYPE 声明语句来指明它所遵循的DTD文件,DOCTYPE声明语句有两种形式:

 

当引用的文件在本地时,采用如下方式:

<!DOCTYPE 文档根结点 SYSTEM "DTD文件的URL">

例如: <!DOCTYPE 书架 SYSTEM “book.dtd”>。

 

当引用的文件是一个公共的文件时,采用如下方式:

<!DOCTYPE 文档根结点 PUBLIC "DTD名称" "DTD文件的URL">

 

DTD约束语法细节:

元素定义

属性定义

实体定义

元素定义1:

DTD文档中使用ELEMENT声明一个XML元素,语法格式如下所示:

 <!ELEMENT 元素名称 元素类型>

元素类型可以是元素内容、或类型

如为元素内容:则需要使用()括起来,如

<!ELEMENT 书架 <有空格>  (书名,作者,售价)>

<!ELEMENT 书名 <有空格>  (#PCDATA)>

如为元素类型,则直接书写,DTD规范定义了如下几种类型:

EMPTY:用于定义空元素,例如<br/> <hr/>

ANY:表示元素内容为任意类型。(建议少用)

元素内容中可以使用如下方式,描述内容的组成关系

 元素内容使用空白符分隔,表示出现顺序没有要求:<!ELEMENT MYFILE (TITLE AUTHOR EMAIL)> ×

 用逗号分隔,表示内容的出现顺序必须与声明时一致。<!ELEMENT MYFILE (TITLE,AUTHOR,EMAIL)>

 |分隔,表示任选其一,即多个只能出现一个

<!ELEMENT MYFILE (TITLE|AUTHOR|EMAIL)>

在元素内容中也可以使用+、*、?等符号表示元素出现的次数:

+: 一次或多次 (书+)

 ?: 0次或一次 (书?)

 *: 0次或多次  (书*)  或  (书)有且只有一次

也可使用圆括号( )批量设置,例

<!ELEMENT MYFILE ((TITLE*, AUTHOR?, EMAIL)* | COMMENT)>

 

 

 

 

 

属性定义

xml文档中的标签属性需通过ATTLIST为其设置属性

语法格式:

<!ATTLIST 元素名

属性名1 属性值类型 设置说明

属性名2 属性值类型 设置说明

……

>

属性声明举例:

<!ATTLIST 商品

类别 CDATA #REQUIRED

颜色 CDATA #IMPLIED

>

对应XML文件:

<商品 类别="服装" 颜色="黄色">…</商品>

<商品 类别="服装">…</商品>

 

设置说明:

#REQUIRED:必须设置该属性

#IMPLIED:可以设置也可以不设置

#FIXED:说明该属性的取值固定为一个值,在 XML 文件中不能为该属性设置其它值。但需要为该属性提供这个值

直接使用默认值:在 XML 中可以设置该值也可以不设置该属性值。若没设置则使用默认值。

 

CDATA:表示属性值为普通文本字符串。

ENUMERATED 枚举

ID

ENTITY(实体)

ENUMERATED 枚举

属性的类型可以是一组取值的列表,在 XML 文件中设置的属性值只能是这个列表中的某个值(枚举)

 

ID

表示属性的设置值为一个唯一值。

ID 属性的值只能由字母,下划线开始,不能出现空白字符

引用实体主要在 XML 文档中被应用

 

ENTITY(实体)-----在DTD中定义,在XML中使用

语法格式:

<!ENTITY 实体名称 “实体内容” >:直接转变成实体内容

引用方式:

&实体名称;  

举例:

<!ENTITY copyright “I am a programmer">

 ……

 ©right;

实体定义à参数实体

参数实体被 DTD 文件自身使用

语法格式:

   <!ENTITY % 实体名称 "实体内容" >

引用方式:

%实体名称; 需要使用外部实体。

举例1:

 <!ENTITY % TAG_NAMES "姓名 | EMAIL | 电话 | 地址">

    <!ELEMENT 个人信息 (%TAG_NAMES; | 生日)>

 <!ELEMENT 客户信息 (%TAG_NAMES; | 公司名)>

举例2:

<!ENTITY % common.attributes

 " id ID #IMPLIED

   account CDATA #REQUIRED "

>

...

<!ATTLIST purchaseOrder %common.attributes;>

<!ATTLIST item %common.attributes;>

XML解析器两类:DOM和SAX。

,形成

XML解析方式分为两种:dom和sax

dom:(Document Object Model, 即文档对象模型) 是 W3C 组织推荐的处理 XML 的一种标准方式DOM(文档对象模型)一次性将整个XML文件读到内存,遍历迭代,形成一个倒状的树形结构。

sax: (Simple API for XML) 不是官方标准,但它是 XML 社区事实上的标准,几乎所有的 XML 解析器都支持它。多次将XML文件读到内存。

XML解析器(软件/实现类)

Crimson(SUN)、Xerces(IBM->APACHE) 、Aelfred2(DOM4J开源组织)

XML解析技术API/开发包

Jaxp(SUN/dom/sax)、Jdom、dom4j ........

dom4j为例:

//适用dom4j解析XML文件

public class Demo1 {

public static void main(String[] args) throws Exception {

//创建dom4j解析器

SAXReader saxReader = new SAXReader();//构造函数

//,加载需要解析的xml文件从物理硬盘中读到内存中,Document对象代表XML文件在内存中的映像

Document document = saxReader.read(new File("src/cn/itcast/xml/base/car.xml"));

//获得根元素

Element rootElement = document.getRootElement();

//显示根元素

System.out.println(rootElement.getName());

//取得根元素下的子元素

List<Element> elements = rootElement.elements();

System.out.println("共有"+elements.size()+"辆车");

for (Element e : elements) {

System.out.println("车牌:"+e.elementText("车牌"));

System.out.println("产地:"+e.elementText("产地"));

//element.elements取得该元素下的所有直接子元素

System.out.println("出产时间:"+e.element("车牌").attributeValue("出产时间"));

}

SAXReader saxReader = new SAXReader(); SAXReader是dom4j的核心类

Document document = saxReader.read("*.xml")

Document.getRootElement()

Element.getName()

Element.elements():取得该元素下的所有直接子元素

  Element.elementText():从一个元素导航到另一个元素且取出该元素的文本

Element.element("车牌"):从一个元素导航到另一个元素

Element.attributeValue("出产时间"):取得一个元素对应的属性

Element.addElement("单价").setText("40"):添加新元素,同时设置该元素文本的值

OutputFormat format = OutputFormat.createPrettyPrint():使用缩格形式写XML文件

XMLWriter xmlWriter = new XMLWriter(os,format):构造XML写入器

xmlWriter.write(document):将内存中的document对象写入硬盘

firstCarElement.remove(firstCarPriceElement):从直接父元素删除直接子元素

//firstCarPriceElement.getParent().remove(firstCarPriceElement):从直接父元素删除直接子元素

使用dom4j执行cud操作

增加一个元素

//对每一辆汽车添加“单价”元素,并设置为30

public class Demo1 {

public static void main(String[]args) throws Exception {

//创建dom4j解析器

SAXReader saxReader = new SAXReader();//构造函数

//,加载需要解析的xml文件从物理硬盘中读到内存中,Document对象代表XML文件在内存中的映像

Document document = saxReader.read(new File("src/cn/itcast/xml/base/car.xml"));

//获得根元素

Element rootElement = document.getRootElement();

//取得第一辆汽车

Element firstlement = (Element) rootElement.elements().get(0);

 //添加新元素

Element newElement = firstlement.addElement("单价");

newElement.setText("30");

//将内存中的文件写到硬盘中去

OutputFormat format = OutputFormat.createPrettyPrint();

FileOutputStream os = new FileOutputStream("src/cn/itcast/xml/base/car.xml");

XMLWriter xmlWriter = new XMLWriter(os,format);

xmlWriter.write(document);

xmlWriter.close();

 

 

 

更新操作:把 

<单价>30</单价>------>>>>改为 <单价>60</单价>

//创建dom4j解析器

SAXReader saxReader = new SAXReader();//构造函数

//,加载需要解析的xml文件从物理硬盘中读到内存中,Document对象代表XML文件在内存中的映像

Document document = saxReader.read(new File("src/cn/itcast/xml/base/car.xml"));

//获得根元素

Element rootElement = document.getRootElement();

//取得第一辆汽车

Element firstlement = (Element) rootElement.elements().get(0);

firstlement.element("单价").setText("60");

OutputFormat format = OutputFormat.createPrettyPrint();

FileOutputStream os = new FileOutputStream("src/cn/itcast/xml/base/car.xml");

XMLWriter xmlWriter = new XMLWriter(os,format);

xmlWriter.write(document);

xmlWriter.close();

 

 

删除操作:删除单价元素

//创建dom4j解析器

SAXReader saxReader = new SAXReader();//构造函数

//,加载需要解析的xml文件从物理硬盘中读到内存中,Document对象代表XML文件在内存中的映像

Document document = saxReader.read(new File("src/cn/itcast/xml/base/car.xml"));

//获得根元素

Element rootElement = document.getRootElement();

//取得第一辆汽车

Element firstlement = (Element) rootElement.elements().get(0);

Element firstPriceCarElement = firstlement.element("单价");

firstPriceCarElement.getParent().remove(firstPriceCarElement);

OutputFormat format = OutputFormat.createPrettyPrint();

FileOutputStream os = new FileOutputStream("src/cn/itcast/xml/base/car.xml");

XMLWriter xmlWriter = new XMLWriter(os,format);

xmlWriter.write(document);

xmlWriter.close();

 

作业:需求:

car.xml文件中的所有car元素解析出存入集合,并按照单价对集合中的元素降序后输出

Car.xml

<?xml version="1.0" encoding="UTF-8"?>

 

<车辆清单>

  <汽车>

    <车牌 出产时间="2010年">奥迪</车牌>  

    <产地>北京</产地>  

    <单价>30</单价>

  </汽车>  

  <汽车>

    <车牌 出产时间="2011年">本田</车牌>  

    <产地>广州</产地>

    <单价>60</单价>

  </汽车>

</车辆清单>

 

编写的car类

package cn.itcast.xml.base;

 

public class Carimplements Comparable<Car> {

private String band;

private String place;

private String time;

private int price;

public Car(){}

public String getBand() {

return band;

}

public void setBand(Stringband) {

this.band =band;

}

public String getPlace() {

return place;

}

public void setPlace(Stringplace) {

this.place =place;

}

public String getTime() {

return time;

}

public void setTime(Stringtime) {

this.time =time;

}

public int getPrice() {

return price;

}

public void setPrice(int price) {

this.price =price;

}

@Override

public int compareTo(Carcar) {

if (this.price<car.getPrice()) {

return 1;

}else if (this.price>car.getPrice()) {

return -1;

}else {

return 0;

}

}

}

 

测试类

package cn.itcast.xml.base;

 

import java.io.File;

import java.util.ArrayList;

import java.util.Collections;

import java.util.List;

 

import org.dom4j.Document;

import org.dom4j.DocumentException;

import org.dom4j.Element;

import org.dom4j.io.SAXReader;

 

public class MyDemo {

public static void main(String[]args) throws Exception {

SAXReader saxReader = new SAXReader();

Document document = saxReader.read(new File("src/cn/itcast/xml/base/car.xml"));

List<Element> elementList = document.getRootElement().elements();

ArrayList<Car> carList = new ArrayList<Car>();

for (Element e: elementList) {

Car car = new Car();

car.setBand(e.elementText("车牌"));

car.setPlace(e.elementText("产地"));

car.setTime(e.element("车牌").attributeValue("出产时间"));

car.setPrice(Integer.parseInt(e.elementText("单价")));

carList.add(car);

}

System.out.println("-----------排序前-----------");

show(carList);

System.out.println("-----------排序后-----------");

sortByPriceDesc(carList);

}

 

private static void sortByPriceDesc(ArrayList<Car>carList) {

Collections.sort(carList);

show(carList);

}

 

private static void show(ArrayList<Car>carList) {

if (carList!=null &&carList.size()>0) {

for (Car car : carList) {

System.out.println("车牌:"+car.getBand());

System.out.println("单价:"+car.getPrice());

System.out.println("产地:"+car.getPlace());

System.out.println("出产时间:"+car.getTime());

}

}

}

}

 

 

 

解析XML形式的文本,得到document对象

                   String text = "<members></members>";
              Document document = DocumentHelper.parseText(text);

package cn.itcast.xml.base;

 

import java.io.*;

 

import org.dom4j.Document;

import org.dom4j.DocumentException;

import org.dom4j.DocumentHelper;

import org.dom4j.io.OutputFormat;

import org.dom4j.io.XMLWriter;

 

public class Demo4 {

public static void main(String[]args) throws Exception {

String labelString="<China><city>hangzhou</city></China>";

Document document = DocumentHelper.parseText(labelString);

OutputFormat format = OutputFormat.createPrettyPrint();

OutputStream os = new FileOutputStream("src/cn/itcast/xml/base/string2xml.xml");

XMLWriter xmlWriter = new XMLWriter(os,format);

xmlWriter.write(document);

xmlWriter.close();

}

}

主动创建document对象(创建)

                  Document document = DocumentHelper.createDocument();
             //创建根节点

                  Element root = document.addElement("members");

创建空的XML文件:

Document document = DocumentHelper.createDocument();

OutputFormat format = OutputFormat.createPrettyPrint();

OutputStream os = new FileOutputStream("src/cn/itcast/xml/base/empty.xml");

XMLWriter xmlWriter = new XMLWriter(os,format);

xmlWriter.write(document);

xmlWriter.close();

指定插入次序:

<?xml version="1.0" encoding="UTF-8"?>

 

<车辆清单> 

  <汽车> 

    <车牌 出产时间="2010年">奥迪</车牌>  

    <产地>北京</产地>  

    <单价>30</单价> 

  </汽车>  

  <汽车>这是我的汽车</汽车>

  <汽车> 

    <车牌 出产时间="2011年">本田</车牌>  

    <产地>广州</产地>  

    <单价>60</单价> 

  </汽车> 

</车辆清单>

 

public static void main(String[]args) throws Exception {

SAXReader saxReader = new SAXReader();

Document document = saxReader.read("src/cn/itcast/xml/base/car.xml");

List<Element> elementList = document.getRootElement().elements();

Element newCareElement = DocumentHelper.createElement("汽车");

newCareElement.setText("这是我的汽车");

elementList.add(1, newCareElement);

OutputFormat format = OutputFormat.createPrettyPrint();

OutputStream os = new FileOutputStream("src/cn/itcast/xml/base/car.xml");

XMLWriter xmlWriter = new XMLWriter(os,format);

xmlWriter.write(document);

xmlWriter.close();

}

需求:XML---->String

public static void main(String[]args) throws Exception {

SAXReader saxReader = new SAXReader();

Document document = saxReader.read("src/cn/itcast/xml/base/car.xml");

Element rootElement = document.getRootElement();

String xmlString = rootElement.asXML();

System.out.println(xmlString);

}

使用xpath技术取得xml文件中任意级别下的内容:

SAXReader saxReader = new SAXReader();

Document document = saxReader.read(new File("src/cn/itcast/xml/base/car.xml"));

String xpath = "//单价";

List<Element> elementList = document.selectNodes(xpath);

System.out.println(elementList.get(1).getText());

 

*2 基于dom4j的xpath技术

  1)能够在xml文件中,快速定位需要元素,无需从根元素一个一个的导航到需要的子元素

Document.selectNodes():取得所有符合xpath格式的元素

Document.selectSingleNode():取得所有符合xpath格式的元素的第一个元素

Node类型是Element/Text/Attribute/Document/...类型的父接口

关于SAX解析XML技术了解即可