1.schema约束
1.1 schema符合xml的语句,一个xml中可以有多个schema,多个schema使用名称空间区分(类似于java包名)
1.2 dtd里面有PCDATA类型,但是在schema里面可以支持更多的数据类型
-例如:年龄只能是整数,在schema中可以直接定义一个整数类型
1.3 schema语法更加复杂,目前不能替代dtd
2.schema的快速入门
2.1 创建schema文件,后缀名是.xsd,根节点是<schema>
-在<schema>文件里面是有w3c提供的属性和标签,约束xml文件
-属性
xmlns="http://www.w3.org/2001/XMLSchema"表示当前xml文件是一个约束文件
targetNamespace="http://www.example.org/1"使用schema约束文件,直接通过这个地址引入约束文件
elementFormDefault="qualified" 表示schema文件质量良好
(1)步骤:
-看xml中有多少个文件 <element>
-看简单元素还是复杂元素(person为复杂元素)
<element name="person"> <complexType> <sequence> <element name="name" type="string"></element> <element name="age" type="int"></element> </sequence> </complexType> </element>
-简单元素需要在复杂元素里面
-在被约束文件中引入约束文件
xlmns:xsi="http://www.w3.org/2001/XMLSchema-instance"表示xml是一个被约束文件
xmlns="http://www.example.org/1"是约束文档中targetNamespace
xsi:schemaLocation="http://www.example.org/1 1.xsd" targetNamespace 空格 约束文档路径
<?xml version="1.0" encoding="UTF-8"?> <person xlmns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.example.org/1" xsi:schemaLocation="http://www.example.org/1 1.xsd"> <name>zhangsan</name> <age>20</age> </person>>
(2)复杂元素的指示器
<sequence></sequence> :表示元素依照顺序出现
<all></all>:表示元素只能出现一次
<choice></choice>:表示只能出现其中一个元素
<maxOccurs=“”></maxOccurs>:表示元素最多能出现的次数,unbound表示无限次数
<any></any>:表示任意元素
(3)可约束属性
-写在复杂元素里面,写在</complexType>之前,name表示属性名称,type表示属性类型int或string,use表示属性是否必须出现
<attribute name="id1" type="int" use="required"></attribute>
(4)引入多个schema文件,可以给每个起一个别名
3.sax解析的原理
3.1 解析xml的两种技术dom和sax
-sax的解析方式:事件驱动,边读边解析
--当解析到开始标签的时候,自动执行startElement方法,参数qName返回标签名称
--当解析到文本内容的时候,自动执行character方法,通过string的构造方法返回内容
--当解析到结束标签的时候,自动执行endELement方法,参数qName,返回标签名称
-在javax.xml.parsers包下
--SAXParser 此类的实例可以从SAXParserFactory.newsSAXParser() 方法获得
---parse(File f, DefaultHandler dh)
-- SAXParserFactory 实例 newInstance()方法获得
3.2 使用jaxp的sax方式解析xml
(1)sax方式不能实现增删改操作,只能实现查询操作
package cn.itcast.jaxpsax; 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 TestSax { /** * @param args */ public static void main(String[] args)throws Exception { // TODO Auto-generated method stub /* * 1.创建解析器工厂 * 2.创建解析器 * 3.执行parse方法 * 4.自行创建一个类,继承DefaultHandler,重写三个方法 */ //创建解析器工厂 SAXParserFactory saxParserFactory=SAXParserFactory.newInstance(); //创建解析器 SAXParser saxParser=saxParserFactory.newSAXParser(); //执行parse方法 saxParser.parse("src/p1.xml", new MyDefault()); } } class MyDefault extends DefaultHandler{ @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { System.out.print("<"+qName+">"); } @Override public void endElement(String uri, String localName, String qName) throws SAXException { System.out.print("</"+qName+">"); } @Override public void characters(char[] ch, int start, int length) throws SAXException { System.out.print(new String(ch,start,length)); } }
(2)获取到所有的name元素的值
//实现获取所有的name元素的值、 class MyDefault1 extends DefaultHandler{ boolean flag=false; @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { //判断qName是否是name元素 if("name".equals(qName)){ flag=true; } } @Override public void endElement(String uri, String localName, String qName) throws SAXException { //把flag设置成false,把name元素结束 if("name".equals(qName)){ flag=false; } } @Override public void characters(char[] ch, int start, int length) throws SAXException { //当flag值是true时,表示解析到name元素 if(flag==true){ System.out.println(new String(ch,start,length)); } } }
(3)获取第一个name元素的值,添加索引即可
4.使用dom4j解析xml
4.1 dom4j是一个组织,针对xml解析,提供解析器dom4j
-dom4j不是javase的部分,因此需要导包(创建文件夹lib,右键复制jar包到lib下面,右键点击jar包,build path--add to buildpath)
-得到document文件
SAXReader reader = new SAXReader(); Document document = reader.read(url);
-document的父接口是Node,如果在document里面找不到想要的方法,到Node里面去找
-document里面的方法 getRootElement()
:获取根节点,返回的是Element
-element也是一个接口,父节点是Node
-Element和Node里面方法:
--getParent():获取父节点
--addElement:添加标签
4.2 使用dom4j查询xml
package cn.itcast.dom4j; import java.io.IOException; import java.util.List; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; public class TestDom4j { public static void main(String[] args)throws Exception { // TODO Auto-generated method stub selectSin(); } //查询xml中所有name元素的值 /* * 1.创建解析器 * 2.得到document * 3.得到根节点 getRootElement() * 4.得到所有的p1标签 * element(qname):表示获取标签下面的第一个子标签,qname是标签的名称 * elements(qname):获取标签下面是qname名称的所有子标签(一层) * elements():获取标签下面的所有一层子标签 * 5.得到name * 6.得到name里面的值 */ public static void selectName()throws Exception{ //创建解析器 SAXReader saxReader=new SAXReader(); //得到document Document document=saxReader.read("src/p1.xml"); //获取根节点 Element root=document.getRootElement(); //得到所有的p1标签 List<Element> list=root.elements("p1"); //遍历list for(Element element:list){ //element是每一个p1元素 //得到p1下面的name元素 Element name=element.element("name"); //得到name元素里面的内容 String s=name.getText(); System.out.println(s); } } //获取到第一个name元素的值 /* * 1.创建解析器 * 2.得到document * 3.得到根节点 getRootElement() * 4.得到第一个p1元素 * 5.得到p1下面的name元素 * 6.得到name元素里面的值 */ public static void selectSin()throws Exception{ //得到解析器 SAXReader saxReader=new SAXReader(); //得到document Document document=saxReader.read("src/p1.xml"); //得到根节点 Element root=document.getRootElement(); //得到第一个p1元素 Element element=root.element("p1"); //得到p1元素下的name元素 Element nameele=element.element("name"); //得到name元素的内容 String names=nameele.getText(); System.out.println(names); } }
4.3 使用dom4j实现增加
//在第一个p1下面的age标签之前添加<school>ecit.edu.cn</school> /* * 1.创建解析器 * 2.得到document * 3.得到根节点 * 4.获取第一个p1 * 5.获取p1下面的所有元素 elements()方法 返回list集合;使用list里面的方法,在特定位置添加的方法add(int index,Element e) * 6.回写xml * */ public static void addAgeBefore()throws Exception{ //创建解析器 SAXReader saxReader=new SAXReader(); //得到document Document document=saxReader.read("src/p1.xml"); //得到根节点 Element root=document.getRootElement(); //得到第一个p1 Element element=root.element("p1"); //得到p1下面所有的元素 List<Element> list=element.elements(); //创建元素 Element school=DocumentHelper.createElement("school"); //在元素下面创建文本 school.setText("ecit.edu.cn"); list.add(1,school); //回写 OutputFormat format=OutputFormat.createPrettyPrint(); XMLWriter xmlWriter=new XMLWriter(new FileOutputStream("src/p1.xml"),format); xmlWriter.write(document); xmlWriter.close(); } //在第一个p1标签末尾添加一个元素<sex>nv</sex> /* * 1.创建解析器 * 2.得到document * 3.得到根节点 * 4.获取第一个p1 * 5.在p1下面添加元素 * 6.在添加完成之后的元素下面添加文本 * 7.回写xml */ public static void addSex()throws Exception{ //创建解析器 SAXReader saxReader=new SAXReader(); //得到document Document document =saxReader.read("src/p1.xml"); //得到根节点 Element root=document.getRootElement(); //获取第一个p1 Element p1=root.element("p1"); //在p1下面直接添加元素 Element sexnode=p1.addElement("sex"); //在sex下面直接添加文本 sexnode.addText("nv"); //回写xml OutputFormat format=OutputFormat.createPrettyPrint();//有缩进的效果 XMLWriter xmlWriter=new XMLWriter(new FileOutputStream("src/p1.xml"),format); xmlWriter.write(document); xmlWriter.close(); }
4.4 将dom4j中的方法进行封装
package cn.itcast.dom4j; import java.io.FileOutputStream; import org.dom4j.Document; import org.dom4j.io.OutputFormat; import org.dom4j.io.SAXReader; import org.dom4j.io.XMLWriter; public class Dom4jUtils { public static final String PATH="src/p1.xml"; //返回document public static Document getDocument(String path){ //创建解析器 SAXReader saxReader=new SAXReader(); //得到document try{ Document document=saxReader.read(path); return document; }catch(Exception e){ e.printStackTrace(); } return null; } //回写xml的方法 public static void xmlWriters(String path,Document document){ try{ OutputFormat format=OutputFormat.createPrettyPrint();//有缩进的效果 XMLWriter xmlWriter=new XMLWriter(new FileOutputStream(path),format); xmlWriter.write(document); xmlWriter.close(); }catch(Exception e){ e.printStackTrace(); } } }
4.5 使用dom4j修改xml
//修改第一个p1元素下面的age元素的内容 20->30 /* * 1.得到document * 2.得到第一个p1元素 * 3.得到第一个p1下面的age * 4.修改值是30 * 5.回写xml */ public static void modifyAge() throws Exception{ //得到document Document document=Dom4jUtils.getDocument(Dom4jUtils.PATH); //得到第一个元素p1 Element rootele=document.getRootElement(); Element p1ele=rootele.element("p1"); //得到p1下面的age元素 Element ageEle=p1ele.element("age"); //修改age的值 ageEle.setText("30"); Dom4jUtils.xmlWriters(Dom4jUtils.PATH, document); }
4.6 使用dom4j删除节点的操作
//删除第一个p1元素下面的school元素 /* * 1.得到document * 2.得到根节点 * 3.得到第一个p1标签 * 4.得到第一个p1标签下面的school标签 * 5.使用p1删除school * 6.回写xml */ public static void delSch()throws Exception{ //得到document Document document=Dom4jUtils.getDocument(Dom4jUtils.PATH); //得到根节点 Element root=document.getRootElement(); //得到第一个p1元素 Element p1Ele=root.element("p1"); //得到第一个p1元素下面的school Element schEle=p1Ele.element("school"); //删除节点 p1Ele.remove(schEle); //回写xml Dom4jUtils.xmlWriters(Dom4jUtils.PATH, document); }
4.7 使用dom4j实现获取属性值的操作
//获取第一个p1里面的属性id的值 /* * 1.得到document * 2.得到根节点 * 3.得到第一个p1元素 * 4.得到p1里面的属性 */ public static void getValues()throws Exception{ //得到document Document document = Dom4jUtils.getDocument(Dom4jUtils.PATH); // 得到根节点 Element root = document.getRootElement(); // 得到第一个p1元素 Element p1Ele = root.element("p1"); //得到p1里面的属性 String value=p1Ele.attributeValue("id"); System.out.println(value); }
4.8 使用dom4j支持xpath的操作
(1)可以直接获得某元素,不需要层层解析
(2)xpath的第一种形式:/AAA/DDD/BBB :表示一层一层的,AAA下面的 DDD下面的BBB
xpath的第二种形式://BBB:表示和这个名称相同,只要名称是BBB,都可以得到
xpath的第三种形式://*:所有元素
xpath的第四种形式:/BBB[1]:表示第一个BBB元素
/BBB[last]:表示最后一个BBB元素
xpath的第五种形式://BBB[@id]:表示BBB上有id属性的都可以得到
xpath的第六种形式://BBB[@id='b1']:表示元素的名称是BBB,在BBB上面有id属性,属性名称为b1
(3)具体操作,默认情况下,dom4j不支持xpath
step1:引入支持xpath的jar包,使用 jaxen-1.1-beta-6.jar
step2:在dom4j中提供两个方法支持xpath
-selectNodes("xpath表达式") 获取多个节点
-selectSingleNode("xpath表达式") 获取单个节点
(4)源码
package cn.itcast.dom4j; import java.util.List; import org.dom4j.Document; import org.dom4j.Node; public class TestDom4jXpath { /** * @param args */ public static void main(String[] args)throws Exception { // TODO Auto-generated method stub test2(); } //使用xpath实现获取第一个p1下面的那么的值 public static void test2()throws Exception{ /* * 1.得到document * 2.直接使用selectSingleNode("//p1[@id='aaaa']/name")方法得到name元素 */ //得到document Document document=Dom4jUtils.getDocument(Dom4jUtils.PATH); Node node=document.selectSingleNode("//p1[@id='aaaa']/name"); System.out.println(node.getText()); } //查询xml中所有那么元素的值 public static void test1()throws Exception{ /* * 1.得到document * 2.直接使用selectNodes("//name")方法得到所有的name元素 */ //得到document Document document=Dom4jUtils.getDocument(Dom4jUtils.PATH); List<Node> list=document.selectNodes("//name"); //遍历list集合 for (Node node : list) { System.out.println(node.getText()); } } }