目录
xml-概述
万维网联盟(W3C)
万维网联盟(W3C)创建于1994年, 又称W3C理事会, 是Web技术领域最具权威和影响力的标准机构
1994年10月在麻省理工学院计算机科学实验室成立, 建立者蒂姆·伯纳斯·李
到目前为止, W3C已经发布了200多项影响深远的Web技术标准及实施指南
1. 广为业界采用的超文本标记语言HTML
2. 可扩展标记语言xml
3. 帮助残障人士有效获得Web信息的无障碍指南WCAG等
什么是xml?
全称为EXtensible Markup Language, 是一种可扩展的标记语言
标记语言: 通过标签来描述数据的一门语言(标签有时也称之为元素)
可扩展: 标签的名字是可以自定义的
简单理解: xml文件是由很多标签组成的, 而标签的名字是可以自定义的
xml的作用?
1. 存储数据和传输数据
2. 作为软件的配置文件
xml-标签的规则
1. 标签由一对尖括号和合法的标识符组成
<student>
2. 标签必须成对出现
<student></student>
3. 特殊的标签可以不成对, 但是必须写结束标签
</address>
4. 标签中可以定义属性, 属性和标签名用空格隔开, 属性值必须用引号引起来
<student id="1"></student>
5. 标签需要正确的嵌套
<student id="1">
<name>张三</name>
</student>
xml-语法规则
1. xml文件的后缀必须是xml
2. 文档声明必须是第一行第一列, 注释也不能写第一行
<?xml version="1.0" encoding="UTF-8" standalone="yes/no" ?>
version: 必须存在
encoding: 不是必须存在, 表示当前xml字符集, 一般都是UTF-8
standalone: 不是必须存在, 表示当前xml文件是否依赖其他xml, 取值为yes或者no
3.必须存在一个根标签, 有且只能有一个
4. xml文件中可以定义注释信息, 格式为<!--注释内容-->
注释的快捷键: Ctrl+/
5. xml文件中可以定义一下特殊字符
< < 小于
> > 大于
& & 和号
' ' 单引号
" " 双引号
6. xml文件中可以存在CDATA区
<![CDATA[...内容...]]>
<?xml version="1.0" encoding="UTF-8" ?>
<!--文档声明必须在文件的第一行第一列, 注释也不能写第一行-->
<!--注释的快捷键: Ctrl+/-->
<students>
<student id="1">
<name>zhangsan</name>
<age>18</age>
<info><<<>>></info>
<!--CDATA区中可以写简单的文本, 不用复杂的符号代替-->
<message><![CDATA[内容<<< >>>]]></message>
</student>
<student id="2">
<name>lisi</name>
<age>24</age>
</student>
</students>
xml-DOM解析思想
DOM解析思想?
DOM(document Object Model) 文档对象模型
将文档的各个组成部分看做是对应的对象
首先会将xml文件全部加载到内存, 在内存中形成一个树状结构, 在获取对应的值
对象分类
1. Document对象: 整个xml文档
2. Element对象: 所有标签
3. Attribute对象: 所有属性
4. Text对象: 所有文本内容
重点记忆!
DOM解析思想就是一层一层的进入, 一层一层的解析
xml-解析的准备工作
常见的解析工具
JAXP: SUN公司提供的一套xml解析的API
JDOM: 开源组织提供的一套xml解析的API-jdom
* DOM4J: 开源组织提供的一套xml解析的API-dom4j (全称Dom for Java)
pill: 主要用在Android手机端解析xml
DOM4J解析xml文件准备
1. 将dom4j-1.6.1.jar拖入IDEA的libs(新建)文件夹下
2. 对着jar包右键, As library..
3. 查看API入门案例
public class Foo {
public Document parse(URL url) throws DocumentException {
SAXReader reader = new SAXReader();
Document document = reader.read(url);
return document;
}
}
xml-解析代码实现
案例需求:
1. 解析这个xml文件
2. 将解析的数据封装到学生对象中
3. 将学生对象存储到ArrayList集合中
4. 遍历集合
代码示例
public class Test {
public static void main(String[] args) throws DocumentException {
//创建集合
ArrayList<Student> list = new ArrayList<>();
//获取解析器对象
SAXReader reader = new SAXReader();
//将xml加载进内存,获取文档对象
Document document = reader.read("day17\\xml\\student.xml");
//通过文档对象获取根标签students
Element rootElement = document.getRootElement();
//elements(); 获取所有子标签,返回集合
//List list = rootElement.elements();
//System.out.println(list.size()); //2个子标签
//elements("标签名"); 获取所有指定的子标签,返回集合
List<Element> studentElements = rootElement.elements("student");
//遍历集合, element依次表示每一个student标签
for (Element element : studentElements) {
//获取id属性对象(attribute对象), 然后获取id属性值
Attribute attribute = element.attribute("id");
String id = attribute.getValue();
//获取name标签对象(Element对象), 然后获取标签体
Element nameElement = element.element("name");
String name = nameElement.getText();
//获取age标签对象(Element对象), 然后获取标签体
Element ageElement = element.element("age");
String age = ageElement.getText();
//测试
//System.out.println(id+","+name+","+age);
//封装对象并添加到list集合
list.add(new Student(id, name, Integer.parseInt(age)));
}
//遍历集合复习
System.out.println("---------------迭代器");
Iterator<Student> it = list.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
System.out.println("---------------增强for");
for (Student student : list) {
System.out.println(student);
}
System.out.println("---------------普通for");
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
System.out.println("---------------直接打印");
System.out.println(list);
}
}
。。。标准Student类。。。
DTD-入门案例-编写DTD
什么是xml约束?
用来限定xml文件中可以使用的标签以及属性 -> 告诉程序员xml该怎么写
约束分类?
1. DTD
2. schema
DTD约束的编写步骤?
步骤1. 创建一个文件, 后缀为.dtd
步骤2. 看xml文件中使用了哪些元素, <!ELEMENT>可以定义元素
步骤3. 判断简单元素和复杂元素 (后面详细讲解)
* 简单元素: 没有子元素 <!ELEMENT 元素名称 (#PCDATA)> #PCDATA表示是字符串类型
* 复杂元素: 有子元素 <!ELEMENT 元素名称 (子元素名称1,子元素名称2...)>
代码示例
<!ELEMENT persons (person)>
<!ELEMENT person (name,age)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
DTD-入门案例-引入DTD
DTD的学习目标
目标1. 能在xml中引入约束文档
目标2. 能够简单的阅读约束文档
目标3. 根据约束能正确编写xml文件
引入DTD(方式1, 引入本地DTD)
步骤1. 提供person.xml, 书写代码, 引入DTD约束
步骤2. 书写错误标签检测
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE persons SYSTEM 'persondtd.dtd'>
<persons>
<!--可以引用出所有属性-->
<person>
<name>张三</name>
<age>23</age>
</person>
<!--如果书写范围外的标签,会报错<a></a>-->
</persons>
DTD-约束-三种引入方式
方式1. 引入本地DTD: 上个案例所示,
<!DOCTYPE persons SYSTEM 'persondtd.dtd'>
persons代表根标签名称
SYSTEM代表是本地约束文档
''中代表约束文档名称
方式2. 在xml文件内部引入: 在根标签后面, 使用[]直接书写约束内容
<!DOCTYPE persons[
<!ELEMENT persons (person)>
<!ELEMENT person (name,age)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
]>
方式3. 引入网络DTD: <!DOCTYPE persons "约束文档名称" "DTD约束文档的URL">
DTD-语法规则-定义元素
定义属性语法规则?
定义属性的格式: <!ATTLIST 元素名称 属性名称 属性类型 属性约束>
属性类型:
CDATA类型: 普通字符串
属性约束:
#REQUIRED 代表必须的
#IMPLIED 代表不是必须的
#FIXED "1p" value 代表属性值固定的
<!ATTLIST person id CDATA #FIXED "p1"> //表示必须写成p1
<!ATTLIST person id CDATA #REQUIRED> //表示id必须有值, 值随便写
schema-schema和dtd的区别
schema和dtd的区别?
1. schema约束文件也是一个xml文件, 符合xml语法, 这个文件的后缀名为.xsd
2. 一个xml中可以引入多个schema约束文件, 多个schema使用"名称空间"区分 (类似java的包名)
3. DTD中元素的类型比较单一, 常见的是PCDATA, 但是在schema中支持多种元素类型
4. schema语法更加复杂
注意, 理解记忆!
schema可以约束其他xml文件
但是schema本身也是一个xml, 所以也被其他文件约束着
schema入门案例-编写schema
schema约束编写步骤?
1. 创建文件后缀为.xsd
2. 定义文档声明: <?xml version="1.0" encoding="UTF-8" ?>
3. schema文件的根标签为: <schema>, 属性有三个
xmlns="http://www.w3.org/2001/XMLSchema "
targetNamespace="唯一的自定义URL地址"
固定格式表示文件质量良好: elementFormDefault="qualified
4. 通过element定义根标签: <element name="根标签名">
5. 判断复杂元素和简单元素, 复杂元素需要写<complexType>和<sequence>
<!--复杂元素-->
<complexType>
<!--子元素必须按照顺序定义-->
<sequence>
<!--简单元素-->
<element name="属性名" type="string"></element>
<element name="属性名" type="string"></element>
</sequence>
</complexType>
根据xml文件写出schema约束
<?xml version="1.0" encoding="UTF-8" ?>
<cars>
<car>
<brand>宝马</brand>
<price>200000</price>
</car>
</cars>
schema约束代码示例
<?xml version="1.0" encoding="UTF-8" ?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.itheima.cn/javase"
elementFormDefault="qualified"
>
<!--定义复杂元素cars-->
<element name="cars">
<complexType>
<sequence>
<!--定义复杂元素car-->
<element name="car">
<complexType>
<sequence>
<!--定义简单元素name和age-->
<element name="brand" type="string"/>
<element name="price" type="string"/>
</sequence>
</complexType>
</element>
</sequence>
</complexType>
</element>
</schema>
schema入门案例-引入schema
引入schema步骤?
1. 在根标签定义属性
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" //instance表示约束别人
xmlns="引入约束文件的名称空间"
2. 由于有两个xmlns, 给某一个xmlns属性添加标识:xsi
3. 通过xsi:schemaLocation="名称空间 文件路径"
引入schema代码示例
<?xml version="1.0" encoding="UTF-8" ?>
<cars
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.itheima.cn/javase"
xsi:schemaLocation="http://www.itheima.cn/javase carschema.xsd"
>
<car>
<brand>宝马</brand>
<price>200000</price>
</car>
</cars>
schema入门案例-定义属性
schema定义属性?
在约束文件中</sequence>后</complexType>前书写
<attribute name="id" type="string" use="required"></attribute>
use="required" 必须的
use="optional" 可选的
代码示例
//carschema.xsd定义属性id
<?xml version="1.0" encoding="UTF-8" ?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.itheima.cn/javase"
elementFormDefault="qualified"
>
<!--定义复杂元素cars-->
<element name="cars">
<complexType>
<sequence>
<!--定义复杂元素car-->
<element name="car">
<complexType>
<sequence>
<!--定义简单元素name和age-->
<element name="brand" type="string"/>
<element name="price" type="string"/>
</sequence>
<!--定义属性-->
<attribute name="id" type="string" use="required"></attribute>
</complexType>
</element>
</sequence>
</complexType>
</element>
</schema>
//car.xml使用id属性
<?xml version="1.0" encoding="UTF-8" ?>
<cars
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.itheima.cn/javase"
xsi:schemaLocation="http://www.itheima.cn/javase carschema.xsd"
>
<car id="001">
<brand>宝马</brand>
<price>200000</price>
</car>
</cars>
枚举-什么是枚举
思考如果我们要表示固定的几个值, 比如季节: spring, summer, autumn, winter
public static final int SEASON_SPRING = 1;
public static final int SEASON_SUMMER = 2;
public static final int SEASON_AUTUMN = 3;
public static final int SEASON_WINTER = 4;
上述代码的弊端?
1. 代码不够简洁
2. 不同类型的数据, 是通过名字区分的
3. 不安全, 由于是数字类型, 就有可能使用这几个值做算数操作
什么是枚举?
为了简洁的表示一些"固定的值", Java给我们提供了"枚举类型"
枚举是指将变量的值一一列出来, 变量的值仅限于列举出来的值的范围内
枚举-定义格式
枚举的定义格式?
public enum s{
枚举项1,枚举项2,枚举项3,;
}
定义枚举要使用关键字enum
案例代码示例: 使用枚举表示春夏秋冬四个季节
public enum Season {
//枚举项
SPRING,SUMMER,AUTUMN,WINTER
}
枚举的特点
枚举的特点?
1. 所有枚举类都是Enum的子类
2. 我们可以通过"枚举类名.枚举项名称"去访问指定的枚举项
3. 每一个枚举项, 其实就是该枚举类的一个对象 -> 重点记忆, 其他了解即可!
4. 枚举也是一个类, 也"可以声明成员变量"
5. 枚举类的"第一行上必须是枚举项", 如果没有后续代码, 最后一个枚举项后的分号可以省略, 不建议
6. 枚举类"可以有构造器, 但是必须是私有的", 默认是private的, 使用枚举项: 枚举(""){};
7. 枚举类也"可以有抽象方法, 但是枚举项必须重写该方法"
代码示例
public enum Season {
//枚举类的"第一行上必须是枚举项", 如果没有后续代码, 最后一个枚举项后的分号可以省略, 不建议
//SPRING,SUMMER,AUTUMN,WINTER;
//使用枚举项: 枚举(""){};
SPRING("春"){
@Override
public void show() {
System.out.println(this.name);
}
},SUMMER("夏"){
@Override
public void show() {
System.out.println(this.name);
}
},AUTUMN("秋"){
@Override
public void show() {
System.out.println(this.name);
}
},WINTER("冬"){
@Override
public void show() {
System.out.println(this.name);
}
};
//枚举也是一个类, 也"可以声明成员变量"
//private String name;
public String name;
//枚举类"可以有构造器, 但是必须是私有的", 默认是private的
//空参构造: 如果提供带参注释空参, 枚举项(对象)会报错
//private Season() {}
private Season() {}
//带参构造
private Season(String name) {
this.name = name;
}
//抽象方法: 枚举类也"可以有抽象方法, 但是枚举项必须重写该方法"
public abstract void show();
}
/*
枚举的特点?
1. 所有枚举类都是Enum的子类
2. 我们可以通过"枚举类名.枚举项名称"去访问指定的枚举项
3. 每一个枚举项, 其实就是该枚举类的一个对象 -> 重点记忆, 其他了解即可!
4. 枚举也是一个类, 也"可以声明成员变量"
5. 枚举类的"第一行上必须是枚举项", 如果没有后续代码, 最后一个枚举项后的分号可以省略, 不建议
6. 枚举类"可以有构造器, 但是必须是私有的", 默认是private的, 使用枚举项: 枚举(""){};
7. 枚举类也"可以有抽象方法, 但是枚举项必须重写该方法"
*/
class SeasonTest{
public static void main(String[] args) {
//我们可以通过"枚举类名.枚举项名称"去访问指定的枚举项
System.out.println(Season.SPRING); //SPRING
System.out.println(Season.SUMMER); //SUMMER
System.out.println(Season.AUTUMN); //AUTUMN
System.out.println(Season.WINTER); //WINTER
//每一个枚举项, 其实就是该枚举类的一个对象 -> 重点记忆, 其他了解即可!
Season spring = Season.SPRING; //自动生成左边
}
}
枚举的方法
枚举的常用方法?
1. String name(); 获取枚举名称
2. int ordinal(); 返回枚举在枚举类中的索引值
3. int compareTo(E o); 比较两个枚举项, 返回索引差值
4. String toString(); 返回枚举常量名称
5. static <T> T valueOf(Class<T> type, String name);获取指定枚举类中指定名称的枚举值
6. values(); 获得所有枚举项
public class Test {
public static void main(String[] args) {
//1. String name(); 获取枚举名称
String name = Week.MONDAY.name();
System.out.println(name); //MONDAY
System.out.println("------------------------");
//2. int ordinal(); 返回枚举在枚举类中的索引值
System.out.println(Week.MONDAY.ordinal()); //0
System.out.println(Week.TUESDAY.ordinal()); //1
System.out.println(Week.WEDNESDAY.ordinal()); //2
System.out.println(Week.THURSDAY.ordinal()); //3
System.out.println(Week.FRIDAY.ordinal()); //4
System.out.println(Week.SATURDAY.ordinal()); //5
System.out.println(Week.SUNDAY.ordinal()); //6
System.out.println("------------------------");
//3. int compareTo(E o); 比较两个枚举项, 返回索引差值
System.out.println(Week.MONDAY.compareTo(Week.SUNDAY)); //0 - 6 = -6
System.out.println("------------------------");
//4. String toString(); 返回枚举常量名称
String mondayValue = Week.MONDAY.toString();
System.out.println(mondayValue); //MONDAY 一般不会直接用,
System.out.println("------------------------");
//5. static <T> T valueOf(Class<T> type, String name);获取指定枚举类中指定名称的枚举值
Week monday = Enum.valueOf(Week.class, "MONDAY");
System.out.println(monday); //MONDAY
System.out.println(Week.MONDAY == monday); //true
System.out.println("------------------------");
//6. values(); 获得所有枚举项
Week[] week = Week.values();
for (Week value : week) {
// 打印枚举项
System.out.println(value);
/*
MONDAY
MONDAY
TUESDAY
WEDNESDAY
THURSDAY
FRIDAY
SATURDAY
SUNDAY
*/
}
}
}
//枚举星期
enum Week{
MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY,SUNDAY;
}