本节思维导图
Schema学习
Schema简介
XML Schema 是基于 XML 的 DTD 替代者。
XML Schema 描述 XML 文档的结构
XML Schema 语言也可作为 XSD(XML Schema Definition)来引用。
Schema作用
-XML Schema 的作用是定义 XML 文档的合法构建模块,为XML文件添加约束,类似 DTD。
-定义可出现在文档中的元素
-定义可出现在文档中的属性
-定义哪个元素是子元素
-定义子元素的次序
-定义子元素的数目
-定义元素是否为空,或者是否可包含文本
-定义元素和属性的数据类型
-定义元素和属性的默认值以及固定值
Schema优点
Schema是DTD的代替者,比DTD更加强大。
(1)支持数据类型
-可更容易地描述允许的文档内容
-可更容易地验证数据的正确性、
-可更容易地与来自数据库的数据一并工作
-可更容易地定义数据约束
(2)Schema文件本身也是XML文件,使用XML语法
-可使用 XML 编辑器来编辑 Schema 文件
-可使用 XML 解析器来解析 Schema 文件
(3)Schema可保护数据通信
(4)Schema可扩展
-在一个文档中可以引用多个Schema
(5)Schema可以捕获错误
Schema文档
Schema文档后缀名为.xsd
例如:
<?xml version="1.0" encoding="UTF-8"?> //xml文档声明
<schema xmlns="http://www.w3.org/2001/XMLSchema" //固定。显示schema中用到的预定义的元素来自于w3c组织
targetNamespace="XXXXX" //可以随便写,一般写url地址,不容易重复。显示此schema定义的元素来自于这个命名空间。
elementFormDefault="qualified"> //固定。显示schema中用到的预定义的元素来自于w3c组织
</schema>
在XML中引用Schema文件
<根节点 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="schema文档中的targetNamespace的值"
xsi:schemaLocation="targetNamespace的值 xsd文档的路径">
</根节点>
XSD元素
定义简易元素:<element name="xxx" type="yyy"></element>
name代表元素的名称
type代表元素的类型
default代表元素的默认值
fixed代表元素的固定值,不可更改
定义复杂元素:包含子节点或其他元素的元素
<element name="复杂元素名称">
<complexType>
<sequence>
子节点1
子节点2
.......
</sequence>
</complexType>
</element>
例子
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.org/1"
xmlns:tns="http://www.example.org/1"
elementFormDefault="qualified">
<element name="person">
<complexType>
<sequence>
<element name="name" type="string"></element>
<element name="age" type="int"></element>
</sequence>
</complexType>
</schema>
Schema指示器
<sequence></sequence>:规定元素必须按照指定的顺序出现
<all></all>:规定元素可以按照任意顺序出现,且每个元素必须只出现一次
<choice></choice>:规定只能出现其中的一个子元素
元素属性里可以添加Occurrence指示器
maxOccurs:规定元素可出现的最大次数
minOccurs:规定元素出现的最小次数
例子:
<element name="xxx" type="yyy" maxOccurs="10" minOccurs"0"></element>
如需使某个元素的出现次数不受限制,请使用 maxOccurs="unbounded" 这个声明
<any></any>表示可以出现任何元素
SAX解析方式
SAX解析简介:
-SAX解析是从头到尾逐个读取内容,修改不便,适用于只读的大文档。
-SAX采用事件驱动的方式解析文档,就如同电影院看电影一样,从头到尾看一遍,不能回退。
-SAX解析过程中,读取到文档开头结尾,元素开头结尾都会触发一些回调方法。
这四个方法是:startDocument() 、 endDocument()、 startElement()、 endElement
-此外,光读取到节点处是不够的,我们还需要characters()方法来仔细处理元素内包含的内容
将这些回调方法集合起来,便形成了一个类,这个类也就是我们需要的触发器
重要的方法有三个
-读取到元素开始时自动调用startElement方法:
void startElement(String uri, String localName, String qName, Attributes attributes)
qName为元素名
-读取文本内容时自动调用characters方法
void characters(char[] ch, int start, int length)
ch为字符数组,start为开始位置,length为长度,直接new String(ch,start,length)就可获得内容
-读取到元素末尾时自动调用endElement方法
void endElement(String uri, String localName, String qName)
qName为元素名
SAX例子:查询所有元素
xml文件
<?xml version="1.0" encoding="UTF-8"?>
<class>
<person id="001">
<name>zhangsan</name>
<age>500</age>
</person>
<person>
<name>lisi</name>
<age>20</age>
</person>
</class>
//查询所有元素
public class SaxTest {
public static void main(String[] args) throws Exception {
SAXParserFactory saxParserFactory=SAXParserFactory.newInstance(); //先创建解析器工厂
SAXParser saxParser=saxParserFactory.newSAXParser();//通过解析器工厂获得解析器实例
saxParser.parse("WebContent/class.xml", new myHandler());//然后传入被解析的xml文档和触发器,触发器需要自己继承DefaultHandler类
}
}
//继承默认触发器,覆写里面的三个方法,这三个方法都是自动被调用的
class myHandler extends DefaultHandler
{
//覆写三个方法
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
// TODO Auto-generated method stub
System.out.print("<"+qName+">");
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
// TODO Auto-generated method stub
System.out.print(new String(ch,start,length));
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
// TODO Auto-generated method stub
System.out.println("</"+qName+">");
}
}
SAX例子:获取所有name标签里的值
//自定义触发器里面的三个方法,里面的方法是文档被解析时自动被调用的
class myHandler extends DefaultHandler
{
//设置一个标记
boolean flag=false;
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
// TODO Auto-generated method stub
//当标签为name时,标志设为true
if(qName.equals("name"))
{
flag=true;
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
// TODO Auto-generated method stub
//如果标记为true,代表这是name标签,获取里面的值
if(flag)
{
System.out.println(new String(ch,start,length));
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
// TODO Auto-generated method stub
//如果读取到name的末尾,就将标记设置为false
if(qName.equals("name"))
{
flag=false;
}
}
}
DOM4J
dom4j简介
dom4j是一个Java的XML API,是jdom的升级品,用来读写XML文件的。
dom4j是一个十分优秀的JavaXML API,具有性能优异、功能强大和极其易使用的特点。
获取解析器和document文档
SAXReader reader=new SAXReader();
Document document=reader.read(URL);
Document下的方法
getRootElement():获取根节点
Element下的方法
elements():获取标签下的所有子节点,返回值是list集合
elements(QName qName):获取标签下的qName节点,返回值是list集合
element(QName qName):获取标签下的第一个qName节点,返回值是Element
例子:dom4j实现查询操作
xml文档
<?xml version="1.0" encoding="UTF-8"?>
<class>
<person id="001">
<name>zhangsan</name>
<age>500</age>
</person>
<person>
<name>lisi</name>
<age>20</age>
</person>
</class>
//查询所有name标签里的值
public static void selectName() throws Exception
{
//创建解析器
SAXReader saxReader=new SAXReader();
//获取document
Document document=saxReader.read("WebContent/class.xml");
//获取根节点
Element root=document.getRootElement();
//获取根节点下的所有person
List <Element> list=root.elements("person");
//遍历每一个person,获取name值
for(Element element:list)
{
Element name1=element.element("name");
String s=name1.getText();
System.out.println(s);
}
}
//查询第一个name的值
public static void selectFirst() throws Exception
{
//创建解析器
SAXReader saxReader=new SAXReader();
//获取document
Document document=saxReader.read("WebContent/class.xml");
//获取根节点
Element root=document.getRootElement();
//获取第一个person
Element person=root.element("person");
获取第一个name
Element name=person.element("name");
System.out.println(name.getText());
}
例子:dom4j实现末尾添加节点的操作
//在第一个person里添加一个性别(sex)
public static void addSex() throws Exception
{
//获取解析器
SAXReader saxReader=new SAXReader();
//获取document
Document document=saxReader.read("WebContent/class.xml");
//获取根节点
Element root=document.getRootElement();
//获取第一个person
Element person=root.element("person");
//添加节点到末尾
Element sex=person.addElement("sex");
//添加文本
sex.addText("男");
//回写操作
OutputFormat format=OutputFormat.createPrettyPrint();//指定回写的格式,带缩进,一般用这种
//OutputFormat format=OutputFormat.createCompactFormat();//这种格式全在一行,没缩进
XMLWriter writer=new XMLWriter(new FileOutputStream("WebContent/class.xml"), format);//第一个参数为要写入的文件,第二个为格式
writer.write(document);//把内存中的文档树写入到文件中
writer.close();//关闭流
}
例子:dom4j实现在特定位置添加节点
在第一个person里的name下面添加school标签
public static void addIndex() throws Exception
{
//获取解析器
SAXReader saxReader=new SAXReader();
//获取document
Document document=saxReader.read("WebContent/class.xml");
//获取根节点
Element root=document.getRootElement();
//获取第一个person
Element person=root.element("person");
//获取person下的所有标签
List <Element>list=person.elements();
//创建标签
Element school=DocumentHelper.createElement("school");
//添加文本
school.setText("黄淮学院");
//然后通过list集合的add方法将节点添加到指定地方
list.add(1, school);
//回写
OutputFormat format=OutputFormat.createPrettyPrint();
XMLWriter xmlWriter=new XMLWriter(new FileOutputStream("WebContent/class.xml"),format);
xmlWriter.write(document);
xmlWriter.close();
}
例子:使用dom4j修改节点
public static void update() throws Exception
{
//获取解析器
SAXReader saxReader=new SAXReader();
//获取document
Document document=saxReader.read("WebContent/class.xml");
//获取根节点
Element root=document.getRootElement();
//获取第一个person
Element person=root.element("person");
//获取person下的age
Element age=person.element("age");
//修改age
age.setText("500");
//回写操作
OutputFormat format=OutputFormat.createPrettyPrint();
XMLWriter xmlWriter=new XMLWriter(new FileOutputStream("WebContent/class.xml"),format);
xmlWriter.write(document);
xmlWriter.close();
}
例子:通过dom4j删除节点
public static void del() throws Exception
{
//获取解析器
SAXReader saxReader=new SAXReader();
//获取document
Document document=saxReader.read("WebContent/class.xml");
//获取根节点
Element root=document.getRootElement();
//获取第一个person
Element person=root.element("person");
//获取person下的school节点
Element school=person.element("school");
//通过父节点进行删除
person.remove(school);
//回写操作
OutputFormat format=OutputFormat.createPrettyPrint();
XMLWriter xmlWriter=new XMLWriter(new FileOutputStream("WebContent/class.xml"),format);
xmlWriter.write(document);
xmlWriter.close();
}
例子:通过dom4j获取属性的操作
public static void getAttr() throws Exception
{
SAXReader saxReader=new SAXReader();
//获取document
Document document=saxReader.read("WebContent/class.xml");
//获取根节点
Element root=document.getRootElement();
Element person=root.element("person");
//通过attributeValue()方法获取属性值
String s=person.attributeValue("id");
System.out.println(s);
}
XPath学习
xpath简介
-XPath即为XML路径语言,XPath 是一门在 XML 文档中查找信息的语言。
-XPath 用于在 XML 文档中通过元素和属性进行导航。
-XPath基于XML的树状结构,提供在数据结构树中找寻节点的能力。
XPath语法
第一种形式:/AAA/BBB/CCC: 为树形结构,表示AAA下面的BBB下面的CCC节点
第二种形式://BBB:不管在什么位置,选取所有BBB元素
第三种形式:/*:选取这一层的所有元素
第四种形式:
/BBB[1]:表示这一层的第一个BBB元素
/BBB[last()]:表示这一层的最后一个BBB元素
第五种形式:
//@id:表示选取所有的id属性
//BBB[@id]:表示选择有id属性的BBB元素
//BBB[@*]:表示选择有任意属性的BBB元素
//BBB[not(@*)]:选择没有属性的BBB元素
第六种形式:
//BBB[@id='b1']:表示选取含有属性id并且id值为b1的BBB元素
第七种形式://*[count(BBB=2)]:选择含有两个BBB元素的节点
使用dom4j支持xpath
用dom4j查询虽然已经方便很多,但是每次查询都要一层一层的查,使用xpath可以
快速的定位到需要的节点。
要首先导入支持xpath的jar包。
在dom4j里有提供两个方法、
selectNodes("xpath表达式"):返回多个节点
selectSingleNode("xpath表达式"):返回单个节点
例子:使用xpath查询所有name节点的值
public static void selectAll() throws Exception
{
//获取解析器
SAXReader saxReader=new SAXReader();
//获取document文档
Document document=saxReader.read("WebContent/class.xml");
//使用selectNodes方法查询xpath语法获得集合
List <Node> list= document.selectNodes("//name");
for(Node node:list)
{
String s=node.getText();
System.out.println(s);
}
}
例子:使用xpath查询第一个person下面的name值
public static void selectFirst() throws Exception
{
SAXReader saxReader=new SAXReader();
Document document=saxReader.read("WebContent/class.xml");
//第一个person有id=‘001’,可以通过这个直接定位
Node name=document.selectSingleNode("//person[@id='001']/name");
String s=name.getText();
System.out.println(s);;
}
综合应用:学生管理系统XML文件的基本操作
student.xml
<?xml version="1.0" encoding="UTF-8"?>
<school>
<class>
<student>
<id>001</id>
<name>张三</name>
<age>19</age>
</student>
<student>
<id>002</id>
<name>李四</name>
<age>30</age>
</student>
</class>
</school>
例子:往student.xml文件中添加一个学生
public static void addStu() throws Exception
{
//创建解析器
SAXReader saxReader=new SAXReader();
//获取指定文档
Document document=saxReader.read("WebContent/student.xml");
//获取根节点
Element root= document.getRootElement();
//获取根节点下的class节点
Element class1=root.element("class");
//添加学生节点
Element student=class1.addElement("student");
//在学生节点下面依次添加id,name,age等节点
Element id=student.addElement("id");
Element name=student.addElement("name");
Element age=student.addElement("age");
//设置值
id.setText("003");
name.setText("王五");
age.setText("30");
//回写操作
OutputFormat format=OutputFormat.createPrettyPrint();
XMLWriter xmlWriter=new XMLWriter(new FileOutputStream("WebContent/student.xml"),format);
xmlWriter.write(document);
xmlWriter.close();
}
例子:删除学生
public static void delStu(String id) throws Exception
{
//创建解析器
SAXReader saxReader=new SAXReader();
//获取指定文档
Document document=saxReader.read("WebContent/student.xml");
//利用xpath获取所有id标签
List<Node> list=document.selectNodes("//id");
//通过循环判断哪个与传入的id相等
for(Node node:list)
{
//如果相等,就获得id的父节点的父节点,然后删除父节点
if((node.getText()).equals(id))
{
Element parent=node.getParent();
Element school=parent.getParent();
school.remove(parent);
}
}
//回写操作
OutputFormat format=OutputFormat.createPrettyPrint();
XMLWriter xmlWriter=new XMLWriter(new FileOutputStream("WebContent/student.xml"),format);
xmlWriter.write(document);
xmlWriter.close();
}
例子:查询学生
public static void selectStu(String id) throws Exception
{
//创建解析器
SAXReader saxReader=new SAXReader();
//获取指定文档
Document document=saxReader.read("WebContent/student.xml");
//获取所有id的集合
List<Node> list=document.selectNodes("//id");
//通过循环判断哪个与传入的id相等
for(Node node:list)
{
//如果相等,就获得id的父节点,通过父节点来获取到所有学生的信息,进行打印
if((node.getText()).equals(id))
{
Element parent=node.getParent();
Element name=parent.element("name");
Element age=parent.element("age");
System.out.println("id:"+node.getText()+"name:"+name.getText()+"age:"+age.getText());
}
}
}