XML学习笔记二

1、schema约束简介
一个xml中可以有多个schema,用名称空间区分,相比于dtd约束,schema支持更多的类型,约束的更严格。schema符合xml的语法规范,有根节点,该根节点就是schema


image.png

2、schema快速入门
(1)、创建schema文件,后缀名为.xsd
(2)、看xml文件中有多少个元素,就写多少个<element>
(3)、分辨简单元素和复杂元素:

<?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="string"></element>
            </sequence>
        </complexType>
    </element>
</schema>

(4)、在xml文件中引入约束文件

<?xml version="1.0" encoding="UTF-8"?>
<person xmlns: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>
image.png

<sequence>:表示元素出现的顺序
把<sequence>换成<all>则表示元素只能出现一次,换成<choice>表示只能出现其中一个元素

3、sax解析原理
概念见xml学习笔记一中的xml的dom和sax两种解析技术
sax解析:事件驱动,边读边解析

在javax.xml.parsers包内有两个类:
SAXParser类:通过saxParserFactory.newSAXParser()得到实例
SAXParserFactory类:通过SAXParserFactory.newInstance()得到实例


sax解析过程

4、使用jaxp的sax方式解析xml:
sax方式不能实现增删改操作,只能实现查询操作。
TestSax.java文件内容:

package cn.itcast.jaxsax;

import java.io.IOException;

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 {

    public static void main(String[] args) throws Exception{
        /*
         * 1、创建解析器工厂
         * 2、创建解析器
         * 3、执行parse方法解析xml文件
         * 4、创建一个类,继承DefaultHandler
         * 5、重写handler中的三个方法
         * */
        //创建解析器工厂
        SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
        //创建解析器
        SAXParser saxParser = saxParserFactory.newSAXParser();
        //执行parse方法解析xml文件
        saxParser.parse("src/person.xml", new MyDefaultHandler());
    }
}

//创建一个类,继承DefaultHandler
class MyDefaultHandler extends DefaultHandler{
    //重写DefaultHandler的下述三个方法
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes)
            throws SAXException {
        // TODO Auto-generated method stub
        System.out.println("start: " + qName);
    }
    
    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        // TODO Auto-generated method stub
        System.out.println("text: " + 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("end: " + qName);
    }
}

person.xml文件内容:

<?xml version="1.0" encoding="UTF-8"?>
<person>
    <p1>
        <name>ZhangSan</name>
        <age>20</age>
    </p1>
    <p1>
        <name>LiSi</name>
        <age>21</age>
    </p1>
</person>
运行结果

5、使用dom4解析xml
dom4j是一个组织,针对xml解析,提供解析器dom4j,文档:https://dom4j.github.io/,API:https://dom4j.github.io/javadoc/1.6.1/

dom4j不是javaSE的一部分,需要在工程中导入dom4j的jar包:
在MyEclipse中右键点击工程文件夹,创建一个lib文件夹,
复制dom4j.jar到lib文件夹下,
右键dom4j.jar,点build path->add to buildPath,当出现奶瓶样符号的jar包时说明导入成功。


image.png

使用dom4j得到document:

import java.net.URL;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;

public class Foo {

    public Document parse(URL url) throws DocumentException {
        SAXReader reader = new SAXReader();
        Document document = reader.read(url);
        return document;
    }
}

6、使用dom4j实现查询操作
查询所有name元素里面的值:
TestDom4j.java文件内容:

package cn.itcast.dom4j;

import java.util.List;

import javax.xml.parsers.SAXParserFactory;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class TestDom4j {
    public static void main(String[] args) throws Exception{
        //创建解析器
        SAXReader saxReader = new SAXReader();
        //获取document
        Document document = saxReader.read("src/person.xml");
        //获取根节点
        Element root = document.getRootElement();
        //获得所有的p1标签
        List<Element> p1List = root.elements();
        //使用增强for循环遍历p1 list
        for(Element p1 : p1List){
            //获取name标签
            Element name = p1.element("name");
            //打印name中的值
            System.out.println(name.getText());
        }
    }
}

person.xml文件内容:

<?xml version="1.0" encoding="UTF-8"?>
<person>
    <p1>
        <name>ZhangSan</name>
        <age>20</age>
    </p1>
    <p1>
        <name>LiSi</name>
        <age>21</age>
    </p1>
</person>
运行结果

7、在第一个p1标签后添加新元素<sex>nv</sex>:

package cn.itcast.dom4j;

import java.io.FileOutputStream;
import java.util.List;

import javax.xml.parsers.SAXParserFactory;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

public class TestDom4j {
    
    public static void main(String[] args) throws Exception{
//      selectAllName();
        addSex();
    }

    private static void selectAllName() throws DocumentException {
        //创建解析器
        SAXReader saxReader = new SAXReader();
        //获取document
        Document document = saxReader.read("src/person.xml");
        //获取根节点
        Element root = document.getRootElement();
        //获得所有的p1标签
        List<Element> p1List = root.elements();
        //使用增强for循环遍历p1 list
        for(Element p1 : p1List){
            //获取name标签
            Element name = p1.element("name");
            //打印name中的值
            System.out.println(name.getText());
        }
    }
    
    private static void addSex() throws Exception{
        //创建解析器
        SAXReader saxReader = new SAXReader();
        //获取document
        Document document = saxReader.read("src/person.xml");
        //获取根节点
        Element root = document.getRootElement();
        //获得第一个p1标签
        Element p1 = root.element("p1");
        //在p1下添加元素
        Element sex = p1.addElement("sex");
        //在sex下添加文本
        sex.addText("nv");
        
        //回写操作
        OutputFormat format = OutputFormat.createPrettyPrint();
        XMLWriter xmlWriter = new XMLWriter(new FileOutputStream("src/person.xml"), format);
        xmlWriter.write(document);
        xmlWriter.close();
    }
}
效果

8、使用dom4j支持XPATH的操作
可以直接获取某个元素,而不用像前文的一层一层的获取。
-第一种形式:/AA/DD/BB,一层一层的解析得到BB
-第二种形式://BB,只要名称为BB就得到
-第三种形式:/*,表示所有元素都得到
-第四种形式:BBB[1]表示第一个BBB元素,BBB[last()]表示最后一个BBB元素
-第五种形式://BBB[@id],只要元素BBB上有id属性则就得到
-第六种形式://BBB[@id='b1'],得到有属性id且属性值为b1的BBB元素

9、使用dom4j支持XPATH的具体操作
一、导入支持XPATH的dom4j的jar包:jaxen-1.1-beta-6.jar。
二、使用:
获取多个节点:selectNodes("xpath表达式");
获取单一节点:selectSingleNode("xpath表达式");

10、简单学生信息管理系统


系统工程组成

student.xml文件内容:

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

<student> 
  <stu> 
    <id>100</id>  
    <name>ZhangSan</name>  
    <age>21</age> 
  </stu>  
  <stu> 
    <id>101</id>  
    <name>LiSi</name>  
    <age>22</age> 
  </stu> 
</student>

StuService.java文件内容:

package cn.itcast.service;

import java.io.FileOutputStream;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.SAXWriter;
import org.dom4j.io.XMLWriter;

import cn.itcast.vo.*;

public class StuService {
    
    //增加操作
    public static void addStudent(Student student) throws Exception{
        //创建解析器
        SAXReader saxReader = new SAXReader();
        //获取document
        Document document = saxReader.read("src/student.xml");
        //获取根节点student
        Element root = document.getRootElement();
        //在根节点上添加stu节点
        Element stu = root.addElement("stu");
        //在stu节点上依次添加id,name,age
        Element id = stu.addElement("id");
        Element name = stu.addElement("name");
        Element age = stu.addElement("age");
        //依次为id,name,age添加值
        id.setText(student.getId());
        name.setText(student.getName());
        age.setText(student.getAge());
        //回写操作
        OutputFormat format = OutputFormat.createPrettyPrint();
        XMLWriter xmlWriter = new XMLWriter(new FileOutputStream("src/student.xml"), format);
        xmlWriter.write(document);
        xmlWriter.close();
    }
    
    //删除操作,根据学生的id删除
    public static void delStudent(String delId) throws Exception{
        //创建解析器
        SAXReader saxReader = new SAXReader();
        //获取document
        Document document = saxReader.read("src/student.xml");
        //获取根节点student
        Element root = document.getRootElement();
        //使用XPATH获取id节点list
        List<Element> idList = root.selectNodes("//id");
        //遍历id的list,获取每个id的值
        for(Element id : idList){
            //判断当前id的值与要删除的id值是否相同
            if(id.getText().equals(delId)){
                //若相同,则获取当前id父节点stu的父节点,然后利用其父节点将该stu节点删除
                Element stu = id.getParent();
                Element stuParent = stu.getParent();
                stuParent.remove(stu);
            }
        }
        
        //回写操作
        OutputFormat format = OutputFormat.createPrettyPrint();
        XMLWriter xmlWriter = new XMLWriter(new FileOutputStream("src/student.xml"), format);
        xmlWriter.write(document);
        xmlWriter.close();
    }
    
    //查询操作,根据id查询
    public static Student getStudent(String ID) throws Exception{
        Student student = new Student();
        //创建解析器
        SAXReader saxReader = new SAXReader();
        //获取document
        Document document = saxReader.read("src/student.xml");
        //获取根节点student
        Element root = document.getRootElement();
        //使用XPATH获取id节点list
        List<Element> idList = root.selectNodes("//id");
        //遍历id的list,获取每个id的值
        for(Element id : idList){
            //判断当前id的值与要删除的id值是否相同
            if(id.getText().equals(ID)){
                //若相同,则获取当前id父节点stu的父节点
                Element stu = id.getParent();
                //获取该stu的id,name,age
                String getID = stu.elementText("id");
                String getName = stu.elementText("name");
                String getAge = stu.elementText("age");
                student.setId(getID);
                student.setName(getName);
                student.setAge(getAge);
            }
        }
        return student; 
    }

}

Student.java文件内容:

package cn.itcast.vo;

public class Student {
    
    private String id;
    private String name;
    private String age;
    
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getAge() {
        return age;
    }
    public void setAge(String age) {
        this.age = age;
    }
}

TestStu.java文件内容:

package cn.itcast.test;

import cn.itcast.vo.*;
import cn.itcast.service.*;

public class TestStu {

    public static void main(String[] args) throws Exception {
//      testAdd();
//      testDel();
        testGet();
    }
    
    public static void testAdd() throws Exception{
        Student stu = new Student();
        stu.setId("103");
        stu.setName("WangWu");
        stu.setAge("23");
        StuService.addStudent(stu);
    }
    
    public static void testDel() throws Exception{
        StuService.delStudent("103");
    } 
    
    public static void testGet() throws Exception{
        Student stu = StuService.getStudent("100");
        System.out.println(stu.getName());
    }

}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容

  • 1. XML总结 1.1. XML简介 XML : 可扩展的标记语言。(和HTML非常类似的) 可扩展的。 自定义...
    Ethan_Walker阅读 2,984评论 0 12
  • day5 一、表单提交方式 1.使用submit提交 2.使用button提交表单 3.使用超链接提交 4.onc...
    mwj610阅读 405评论 0 0
  • 课程内容:XML 安装MyEclipse开发工具 * 破解(看图) * 配置 * 配置工作空间的编码(UTF-...
    流年划破容颜_cc55阅读 1,173评论 0 2
  • 什么是XML? XML:extensiable markup language 被称作可扩展标记语言 XML简单的...
    Java3y阅读 2,396评论 5 41
  • 第一次在简书上写东西,不知道怀着什么样的心情。既有分享想法,又有渴望得到倾听的感觉,又或者给互联网留下一点自己的痕...
    顾别阅读 383评论 0 0