XML--DTD--Schema--DOM--SAX--DOM4J--XPATH

一.  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文件是否獨立存在

 

2.    元素(ELEMENT

元素也稱爲標籤,必須要用結束標籤

如果元素中沒有主題內容,如<tag></tag>可以寫成<tag/>

元素中不能交叉嵌套

一個xml文件有且只能有一個根元素

xml不會忽略空格、回車、製表符

不要以xml開頭,因爲xml作爲保留的存在

 

命名規範:可以用字母、數字、下劃線、減號、英文句點。嚴格區分大小寫

3.    屬性(ATTLIST

命名規範與元素相同

屬性名不能重複,屬性的值必須要以單引號或雙引號引起來

屬性可以用元素的形式代替

 

4.    註釋<!—xxxxx-->

5.    CDATA

把元素看作爲普通字符串,格式:<![CDATA[ ..... ]]>

6.    特殊字符

&amp;     =>   &

&lt;           =>     <

&gt;          =>     >

&quot       =>   “

&apos      =>   ‘

 

7.    處理指令:PI

作用:用來指揮軟件如何解析XML文檔。

語法:<?開頭 ?>結尾

常用的指令:xml-stylesheet引入樣式

 

三.  約束DTD

DTD:Document Type Definition文檔類型定義

作用:約束XML編寫

DTD文件保存到磁盤上時必須使用utf-8

引用DTD的方式:

1.    引用本地的DTD文件

<!DOCTYPE  根節點名稱  SYSTEM  “DTD路徑名稱”>

2.    引用外部公共的DTD文件

<!DOCTYPE  根節點名稱  PUBLIC  “DTD名稱” “DTD的URL”>

 

語法:

1.    元素<ELEMENT>

例:<!ELEMENT 元素名稱 使用規則>

使用規則:

(#PCDATA):普通字符串數據

EMPTY:此元素爲空元素

ANY:表示此元素的主體內容可以爲任何類型

(子元素):指示此元素有哪些子元素。

//如果是逗號隔開,表明必須按照聲明順序去編寫XML文檔,如果子元素用 | 隔開,表明任選其一。

可以用*,?,+表示元素出現的次數:*(0次或一次或多次) ?(0次或一次) +(一次或多次)  什麼都沒有表示必須出現一次。

 

2.    屬性<ATTLIST>

例:<!ATTLIST  元素名稱  屬性名 屬性值類型 設置說明屬性名 屬性值類型 設置說明>

屬性值類型:

CDATA:字符類型

ENUMERATED:枚舉,只能從枚舉中任選其一

ID:表示屬性值必須是唯一

 

設置說明:

#REQUIRED:表示此屬性必須要寫

#IMPLIED:可選的屬性

#FIXED:取值爲一個固定值       #FIXED“值”

直接值:默認值

 

3.    實體

引用實體:在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</售價>
		<類型>計算機類</類型>
	</書>
</書架>


2.    SAX

好處:讀取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());
		}
	}
}


4.    單元測試JUNIT

在Eclipse中可以新建一個Junit Test Case文件,用於對某個類的方法進行測試。

@Before         每測試一個方法之前,都讀取此方法。執行多個方法,此方法也執行多次。

@After             每測試一個方法之後,都讀取此方法。執行多個方法,此方法也執行多次。

 

@BeforeClass   此上述一樣,區別在於,無論執行多少方法,此方法只執行一次。

@AfterClass     如上。

 

@Test              在要執行的測試方法前加@Test

(Timeout=1000)       代表測試的方法執行的時間,如果超過此設置的時間,則測試會不通過。

(exception=java.lang.NullPointException.class)    代表測試的方法需要返回一個指定的異常。

 

Assert.assertEquals(期待值,實際值);

此係列方法很多,還有判斷返回是不是Boolean型的true。具體查API。

      

5.    XPATH

用於在讀取XML中元素時能快速定位一個指定的標籤。

Node node = document.selectSingleNode(“//書[1]”);

關於Xpath的使用規則查看Xpath的文檔。

      

6.    學生成績 案例:

分層結構:

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:書架>

發佈了67 篇原創文章 · 獲贊 8 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章