一. XML作用及应用(XML:ExtensibleMarkup Language)
1. 作用:描述有关系和层次结构的数据
2. 应用:用于软件的配置文件,描述数据
注:在开发中,传统的配置文件使用的是.propeties文件。以key=value的形式。#代码注释
二. XML语法
1. XML文档声明
<?xml version=”1.0” encoding=”utf-8”?>
version:版本号,目前最高版本还是1.0
encoding:指定编码,如果不写,默认的为utf-8。
注意: 当我们用记事本或其它编辑器编辑xml文件,保存时默认使用的是系统编码。xml文件保存的编码应与xml里encoding编码一致,否则会因为写入及读取的编码表不同而出现错误或乱码的情况。
standalone:设置该xml文件是否独立存在
元素也称为标签,必须要用结束标签
如果元素中没有主题内容,如<tag></tag>可以写成<tag/>
元素中不能交叉嵌套
一个xml文件有且只能有一个根元素
xml不会忽略空格、回车、制表符
不要以xml开头,因为xml作为保留的存在
命名规范:可以用字母、数字、下划线、减号、英文句点。严格区分大小写
命名规范与元素相同
属性名不能重复,属性的值必须要以单引号或双引号引起来
属性可以用元素的形式代替
把元素看作为普通字符串,格式:<![CDATA[ ..... ]]>
& => &
< => <
> => >
" => “
&apos => ‘
作用:用来指挥软件如何解析XML文档。
语法:<?开头 ?>结尾
常用的指令:xml-stylesheet引入样式
DTD:Document Type Definition文档类型定义
作用:约束XML编写
DTD文件保存到磁盘上时必须使用utf-8
引用DTD的方式:
1. 引用本地的DTD文件
<!DOCTYPE 根节点名称 SYSTEM “DTD路径名称”>
2. 引用外部公共的DTD文件
<!DOCTYPE 根节点名称 PUBLIC “DTD名称” “DTD的URL”>
语法:
例:<!ELEMENT 元素名称 使用规则>
使用规则:
(#PCDATA):普通字符串数据
EMPTY:此元素为空元素
ANY:表示此元素的主体内容可以为任何类型
(子元素):指示此元素有哪些子元素。
//如果是逗号隔开,表明必须按照声明顺序去编写XML文档,如果子元素用 | 隔开,表明任选其一。
可以用*,?,+表示元素出现的次数:*(0次或一次或多次) ?(0次或一次) +(一次或多次) 什么都没有表示必须出现一次。
例:<!ATTLIST 元素名称 属性名 属性值类型 设置说明属性名 属性值类型 设置说明>
属性值类型:
CDATA:字符类型
ENUMERATED:枚举,只能从枚举中任选其一
ID:表示属性值必须是唯一
设置说明:
#REQUIRED:表示此属性必须要写
#IMPLIED:可选的属性
#FIXED:取值为一个固定值 #FIXED“值”
直接值:默认值
引用实体:在DTD中定义,在XML中使用
语法:<!ENTITY 实体名称 “内容”>
引用:&实体名称;
参数实体:在DTD中定义,在DTD中使用
语法:<!ENTITY %实体名称 “内容”>
引用:%实体名称;
四. XML编程
1. DOM:document object model
好处:CRUD比较方便快捷。
缺点:因为dom解析时会将整个xml文件加载至内存,变成一个对象,占用内存较大。还可能导致内存溢出。
DocumentBuilder dBuilder = DocumentBuilerFactory.newInstance().newDocumentBuilder();
Document document = dBuilder.parse(“xml路径”);
实例:以下文件示例中有对XML文件各种操作
ReadBook.java
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class ReadBook {
public static void main(String[] args) throws Exception {
DocumentBuilderFactory dBuilderFactory = DocumentBuilderFactory
.newInstance();
DocumentBuilder dBuilder = dBuilderFactory.newDocumentBuilder();
Document document = dBuilder.parse("src\\day\\o1\\book.xml");
// test1(document);
// test2(document);
// test3(document);
// test4(document);
// test5(document);
// test6(document);
test7(document);
}
// 1、得到某个具体的节点内容
public static void test1(Document document) {
Node node = document.getElementsByTagName("作者").item(0);
System.out.println(node.getTextContent());
}
// 2、遍历所有元素节点
// public static void test2(Document document) {
// Node root = document.getElementsByTagName("书架").item(0);
// list(root);
// }
//
// public static void list(Node root) {
// if (root instanceof Element)
// System.out.println(root.getNodeName());
// NodeList nodeList = root.getChildNodes();
// for (int x = 0; x < nodeList.getLength(); x++) {
// list(nodeList.item(x));
// }
// }
//上面的代码改成
public static void test2(Node node) {
if (node.getNodeType() == node.ELEMENT_NODE)
System.out.println(node.getNodeName());
NodeList nodeList = node.getChildNodes();
for (int x = 0; x < nodeList.getLength(); x++) {
test2(nodeList.item(x));
}
}
// 3、修改某个元素节点的主体内容
public static void test3(Document document) throws Exception {
Element author = (Element) document.getElementsByTagName("作者").item(0);
author.setTextContent("zhangxiaoxiang");
TransformerFactory tfFactory = TransformerFactory.newInstance();
Transformer tf = tfFactory.newTransformer();
tf.transform(new DOMSource(document), new StreamResult(
new OutputStreamWriter(new FileOutputStream(
"src\\day\\o1\\book.xml"), "gbk")));
}
// 4、向指定元素节点中增加子元素节点
public static void test4(Document document) throws Exception {
Element book = (Element) document.getElementsByTagName("书").item(0);
Element newChild = document.createElement("类型");
Element refChild = (Element) document.getElementsByTagName("作者")
.item(0);
newChild.setTextContent("计算机类");
book.insertBefore(newChild, refChild);
TransformerFactory tfFactory = TransformerFactory.newInstance();
Transformer tf = tfFactory.newTransformer();
tf.transform(new DOMSource(document), new StreamResult(
new OutputStreamWriter(new FileOutputStream(
"src\\day\\o1\\book.xml"), "gbk")));
}
// 5、向指定元素节点上增加同级元素节点
public static void test5(Document document) throws Exception {
Element bookName = (Element) document.getElementsByTagName("书名")
.item(1);
Element newChild = document.createElement("类型");
newChild.setTextContent("计算机类");
Element parentNode = (Element) bookName.getParentNode();
parentNode.appendChild(newChild);
TransformerFactory tfFactory = TransformerFactory.newInstance();
Transformer tf = tfFactory.newTransformer();
tf.transform(new DOMSource(document), new StreamResult(
new OutputStreamWriter(new FileOutputStream(
"src\\day\\o1\\book.xml"), "gbk")));
}
// 6、删除指定元素节点
public static void test6(Document document) throws Exception {
Element price = (Element) document.getElementsByTagName("售价").item(0);
price.getParentNode().removeChild(price);
TransformerFactory tfFactory = TransformerFactory.newInstance();
Transformer tf = tfFactory.newTransformer();
tf.transform(new DOMSource(document), new StreamResult(
new OutputStreamWriter(new FileOutputStream(
"src\\day\\o1\\book.xml"), "gbk")));
}
// 7、操作XML文件属性
public static void test7(Document document) throws Exception {
Element book = (Element) document.getElementsByTagName("书").item(0);
// System.out.println(book.getAttribute("出版社"));
//
// book.setAttribute("出版社", "黑马出版社");
NamedNodeMap nodeMap = book.getAttributes();
for (int x = 0; x < nodeMap.getLength(); x++) {
Attr attr = (Attr) nodeMap.item(x);
System.out.println(attr.getName() + ":::" + attr.getValue());
}
// TransformerFactory tfFactory = TransformerFactory.newInstance();
// Transformer tf = tfFactory.newTransformer();
// tf.transform(new DOMSource(document), new StreamResult(
// new OutputStreamWriter(new FileOutputStream(
// "src\\day\\o1\\book.xml"), "gbk")));
}
}
book.xml
<?xml version="1.0" encoding="gbk" standalone="no"?><书架>
<书 出版社="黑马出版社" 责任人="我">
<书名>JavaOOP</书名>
<类型>计算机类</类型>
<作者>zhangxiaoxiang</作者>
</书>
<书>
<书名>JavaScript</书名>
<作者>王老师</作者>
<售价>5.00</售价>
<类型>计算机类</类型>
</书>
</书架>
好处:读取xml文件快,占用内存小。因为在读取的方式是一行一行读取。只适合xml文件的读取。不适合CUD操作。读一行处理一行
实例:
//获取SAX解析器
SAXParser parser =SAXParserFactory.newInstance().newSAXParser();
//通过SAX解析器得到读取器
XMLReader reader = parser.getXMLReader();
//注册内容处理器
reader.setContentHandler( 传入ContentHandler的实现类);
1. 此处可以自己写一个类实现ContentHandler接口,覆盖所有方法。
2. 还可以写一个内部类,因为DefaultHadler是ContentHandler的实现类,我们可以写一个内部类继承DefaultHadler,复写所需的方法。
需要了解到所有的方法用处及运行过程。
实例:
1. 查找指定的作者名。 2. 把读取到的数据封闭到JAVABEAN中。XML文件同为上面的BOOK.XML文件
SAXReadDemo.java
package jaxp.sax;
import java.io.IOException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
public class SAXReadDemo {
public static void main(String[] args) throws ParserConfigurationException,
SAXException, IOException {
// 得到sax解析器
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
// 得到读取器
XMLReader reader = parser.getXMLReader();
// 注册内容处理器
reader.setContentHandler(new DefaultHandler() {
private boolean flag = false;
private int authorIndex = 0;
@Override
public void startElement(String uri, String localName,
String qName, Attributes attributes) throws SAXException {
if("作者".equals(qName)){
flag = true;
}
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
if(flag && authorIndex==1){
System.out.println(new String(ch,start,length));
}
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if("作者".equals(qName)){
authorIndex++;
}
flag = false;
}
});
// 读取xml文档
reader.parse("src\\book.xml");
}
}
BeanRead.java
package jaxp.sax;
public class BookBean {
private String press;
private String editer;
private String bookname;
private String author;
private String type;
public BookBean() {
// TODO Auto-generated constructor stub
}
public BookBean(String press, String editer, String bookname,
String author, String type) {
super();
this.press = press;
this.editer = editer;
this.bookname = bookname;
this.author = author;
this.type = type;
}
public String getPress() {
return press;
}
public void setPress(String press) {
this.press = press;
}
public String getEditer() {
return editer;
}
public void setEditer(String editer) {
this.editer = editer;
}
public String getBookname() {
return bookname;
}
public void setBookname(String bookname) {
this.bookname = bookname;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
@Override
public String toString() {
return "BookBean [press=" + press + ", editer=" + editer
+ ", bookname=" + bookname + ", author=" + author + ", type="
+ type + "]";
}
}
Read2JavaBean.java
package jaxp.sax;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
public class Read2JavaBean {
/**
* 读取xml文件并将数据封装至javabean中
*/
static final List list = new ArrayList();
public static void main(String[] args) throws Exception {
// 得到sax解析器
SAXParser sax = SAXParserFactory.newInstance().newSAXParser();
// 得到读取器
XMLReader reader = sax.getXMLReader();
// 注册内容处理器
reader.setContentHandler(new DefaultHandler() {
private BookBean book = null;
private String current = null;
@Override
public void startElement(String uri, String localName,
String qName, Attributes attributes) throws SAXException {
if ("书".equals(qName)) {
book = new BookBean();
book.setPress(attributes.getValue(0));
book.setEditer(attributes.getValue(1));
}
if ("书名".equals(qName))
current = qName;
if ("作者".equals(qName))
current = qName;
if ("类型".equals(qName))
current = qName;
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
if ("书名".equals(current))
book.setBookname(new String(ch, start, length));
if ("作者".equals(current))
book.setAuthor(new String(ch, start, length));
if ("类型".equals(current))
book.setType(new String(ch, start, length));
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if ("书".equals(qName)) {
list.add(book);
book = null;
}
current = null;
}
});
// 读取xml文件内容
reader.parse("src\\book.xml");
System.out.println(list);
}
}
3. DOM4J解析器
结合DOM和SAX的优点,在读取时用SAX的原理,在CUD操作时用DOM原理。
实例:XML文件进行CRUD操作。XML文件同为上面的BOOK.XML文件
Dom4JDemo.java
package dom4j;
import java.io.FileWriter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Iterator;
import java.util.List;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
public class Dom4jDemo {
/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
SAXReader reader = new SAXReader();
Document document = reader.read("src//book.xml");
// test1(document);
// test2(document);
// test3(document);
// test4(document);
// test5(document);
// test6(document);
test7(document);
}
// 1、得到某个具体的节点内容
public static void test1(Document document) {
Element root = document.getRootElement();
List<Element> lists = root.elements();
String author = lists.get(1).elementText("作者");
System.out.println(author);
}
// 2、遍历所有元素节点
public static void test2(Document document) {
treeWalk(document.getRootElement());
}
public static void treeWalk(Element element) {
for (int x = 0; x < element.nodeCount(); x++) {
Node node = element.node(x);
if (node instanceof Element) {
System.out.println(node.getName());
treeWalk((Element) node);
} else
System.out.println(node.getText());
}
}
// 3、修改某个元素节点的主体内容
public static void test3(Document document) throws Exception {
Element root = document.getRootElement();
List<Element> list = root.elements();
Element bookE = list.get(1);
Element typeE = bookE.element("类型");
typeE.setText("图书类");
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("gbk");
XMLWriter writer = new XMLWriter(new FileWriter("src//book.xml"),
format);
writer.write(document);
writer.close();
}
// 4、向指定元素节点中增加子元素节点
public static void test4(Document document) throws Exception {
Element root = document.getRootElement();
Element book = root.addElement("书");
book.addAttribute("出版社", "传智");
book.addElement("书名").addText("html");
book.addElement("作者").addText("王昭廷");
book.addElement("类型").addText("动画片");
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("gbk");
XMLWriter writer = new XMLWriter(new FileWriter("src//book.xml"),
format);
writer.write(document);
writer.close();
}
// 5、向指定元素节点上增加同级元素节点
public static void test5(Document document) throws Exception {
Element root = document.getRootElement();
Element bookE = root.element("书");
Element bookNameE = bookE.element("书名");
bookNameE.getParent().addElement("零售价").addText("32.22");
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("gbk");
XMLWriter writer = new XMLWriter(new FileWriter("src//book.xml"),
format);
writer.write(document);
writer.close();
}
// 6、删除指定元素节点
public static void test6(Document document) throws Exception {
Element root = document.getRootElement();
Element book = root.element("书");
Element price = book.element("零售价");
price.getParent().remove(price);
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("gbk");
XMLWriter writer = new XMLWriter(new FileWriter("src//book.xml"),
format);
writer.write(document);
writer.close();
}
// 7、操作XML文件属性
public static void test7(Document document) throws Exception {
Element root = document.getRootElement();
Element book = root.element("书");
for (Iterator<Attribute> it = book.attributeIterator(); it.hasNext();) {
Attribute att = it.next();
System.out.println(att.getName() + "=" + att.getValue());
}
}
}
在Eclipse中可以新建一个Junit Test Case文件,用于对某个类的方法进行测试。
@Before 每测试一个方法之前,都读取此方法。执行多个方法,此方法也执行多次。
@After 每测试一个方法之后,都读取此方法。执行多个方法,此方法也执行多次。
@BeforeClass 此上述一样,区别在于,无论执行多少方法,此方法只执行一次。
@AfterClass 如上。
@Test 在要执行的测试方法前加@Test
(Timeout=1000) 代表测试的方法执行的时间,如果超过此设置的时间,则测试会不通过。
(exception=java.lang.NullPointException.class) 代表测试的方法需要返回一个指定的异常。
Assert.assertEquals(期待值,实际值);
此系列方法很多,还有判断返回是不是Boolean型的true。具体查API。
用于在读取XML中元素时能快速定位一个指定的标签。
Node node = document.selectSingleNode(“//书[1]”);
关于Xpath的使用规则查看Xpath的文档。
分层结构:
UI---JAVABEAN---DAO---UTILS---DB
Utils中的方法为static方法。
Dao 中封装所有对数据库进行操作的方法。如果操作的方式不同,可以创建多个Dao包。然后抽取成Interface。多个Dao包实现此Interface。方便以后选择其它操作方式。
Utils包对于异常的处理原则:
可以抛出:但是调用该工具类的必须处理。也可以不抛
非工具类的异常的处理原则:
看调用者能不能处理,不能处理则不抛。
异常转译和异常链
五. Schema约束
扩展名:xsd 本身也是一个xml文件
1、查看Schema文档,找到根元素,在xml中先编写根元素
<?xmlversion="1.0" encoding="gbk"?>
<书架>
</书架>
2、思考:书架来自哪个名称空间。
使用xmlns关键字(xml namespace)来声明来自的命名空间(查阅schema文档中targetNamespace指定的值)
<?xmlversion="1.0" encoding="gbk"?>
<itheima:书架 xmlns:itheima="http://www.itcast.cn">
</itheima:书架>
3、思考:名称空间对应的xsd文件在何方?
使用schemaLocation来说明名称空间和xsd文件的对应关系。
有2个取值:名称空间和xsd文件路径,两者之间用空格、回车、换行分隔
<?xmlversion="1.0" encoding="gbk"?>
<itheima:书架 xmlns:itheima="http://www.itcast.cn"
schemaLocation="http://www.itcast.cnbook.xsd">
</itheima:书架>
4、思考:schemaLocation又哪来的呢?来自W3C的标准名称空间
http://www.w3.org/2001/XMLSchema-instance
<?xmlversion="1.0" encoding="gbk"?>
<itheima:书架 xmlns:itheima="http://www.itcast.cn"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.itcast.cnbook.xsd">
</itheima:书架>