Web基础:xml

XML

eXtensible Markup Language,主要用于自定义标记。

相较于它的兄弟HTML,XML语法十分严谨,不像HTML能够交叉嵌套,甚至有些标签可以省略掉结束标签。由于其语法的严谨性,能保证使用一个

统一的解析器进行解析,从而能确保跨平台的实现,以及互操作性。

常用解析器包括:MSXML、OpenXML、IBM XML4J、Apache Xerces、Oracel XML Parser等。


应用范围

数据交换

web service

数据管理(数据库)

系统配置


技术体系

校验(DTD+Schema)

显示与转换(XSL)

查询(XPath)

API(DOM+SAX)

链接(XLinker+XPointer)


构成


XML文档声明

<?xml version="1.0" encoding = "utf-8"? standalone="yes">

文档声明有以下两个规范。

1.声明放在XML文档的开头。

2.声明一般包括三部分:

version

版本,目前常用XML1.0。

encoding

字符编码,默认为UTF-8。

standalone

文档定义是否在同一个文件内。

*处理指令:

以“<?”开始,以“?>”结束,用于被解析器解析。


文档类型声明

DOCTYPE,紧随XML声明,包含实体声明等DTD内容。

<!DOCTYPE 根元素 [
	<!ENTITY 实体名 "实体内容">
]>


实体

相当于全局变量的作用,置于文档类型声明中。

实体定义格式为:

<!ENTITY 实体名 实体内容>

预定义实体:

<:&lt;

>:&gt;

&:&amp;

":&quot;

':&apos;

引用实体:

&实体名;,例:

<!DOCTYPE currencyType [
	<!ENTITY dollar "$">
]>
<currencyType >$</currencyType >


根元素

每个XML文档的根元素有且仅有一个。


文本内容

PCDATA(Parsed Character Data)。文本内容中的特殊字符,需要用实体代替。

<![PCDATA[content]]>

其中的标签字符将被解析器当做元素处理,实体将展开。


纯文本内容

CDATA(Character Data),全部当做文本处理,其中的任何字符都不被解析器解析。

<![CDATA[content]]>


注释

<!--注释内容-->

注释不能嵌套,不能出现在标记内部。


属性

属性值用引号包住,不能包含特殊符号(需转义)。


良构

一个良构的XML文档能够被解析器正确解析。良构需要满足以下两方面的要求。

结构规范

1.必须有声明语句。

2.必须有且仅有一个根元素。

3.属性值用引号包含。

4.标记成对,无交叉嵌套,空标记正确关闭。

元素规范

1.不能以数字和下划线开头。

2.不能以任何大小写xml开头。

3.不能包含空格。

4.不能包含冒号。

如下是一个良构的XML。


<?xml version="1.0" encoding = "utf-8" standalone="yes"?>
<person>
	<job>
		<name>CEO</name>
		<type>IT</type>
		<money>$10</money>
	</job>
	<family>
		<wife sex="female"></wife>
		<house area="200" money="$3000000"></house>
		<cars>
			<car brand="benz"></car>
			<car brand="landroller"></car>
		</cars>
	</family>
</person>


DTD

Document Type Definition,一套用于校验、规范XML的规,能够指示XML文档的良构。

DTD不能跨平台,Schema弥补了这一缺陷。

定义位置

1.XML文档内部

<!DOCTYPE person[...]>

2.引用外部DTD

<!DOCTYPE person SYSTEM "person_dtd.dtd">

3.引用公共DTD

<!DOCTYPE person PUBLIC "url">


元素规范

用于规范元素的结构、内容,定义在文档类型声明中,其格式为:

<!ELEMENT 元素名 (规范内容)>

例:

<?xml version="1.0"?>
<!DOCTYPE books[
	<!ELEMENT books (book+)>
	<!ELEMENT book (price?,name?)>
	<!ELEMENT price (#PCDATA)>
	<!ELEMENT name (#PCDATA)>
]>

上例中的规范意义如下:

#PCDATA:元素内容可为任意字符串,但不再包含子元素。

EMPTY:元素必须为空。

ANY:元素内容可包含任意在DTD中定义的元素。

其中,符号的意义为:

?:出现且仅出现一次。

+:出现不少于一次。

*:不出现或出现任意次。

():给子元素分组。

|:选择一个子元素。

,:指定元素出现的顺序。


属性规范

用于规范属性的值,格式如下:

<!ATTLIST 元素 
	属性名1 属性类型/属性值 约束
	属性名2 属性类型/属性值 约束	
	......
>

约束包括:

#REQUIRED必填属性。

#IMPLIED:属性可有可无。

#FIXED:属性值必须为属性类型指定的内容。

"默认值":为属性提供默认值。

例:

<!ATTLIST person
	name CDATA #REQUIRED
	age CDATA #REQUIRED
	sex (male|female) #REQUIRED
	occupation CDATA #IMPLIED
	nationality "CHINESE" #FIXED
	salary CDATA "0.0"
>


实例

如下的XML文档(books.xml)将被下文使用。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE books [
	<!ELEMENT books (category+)>
	<!ELEMENT category (book+)>
	<!ELEMENT book (title?,author?)>
	<!ELEMENT title (#PCDATA)>
	<!ELEMENT author (#PCDATA)>
	<!ATTLIST category
		id CDATA #REQUIRED
		name CDATA #REQUIRED>
	<!ATTLIST book
		id CDATA #REQUIRED
		price CDATA	"0.0">
]>
<books>
	<category id="01" name="Novel">
		<book id="0101" price="100.5">
			<title>War And Peace</title>
			<author>Tolstoy</author>
		</book>
		<book id="0102"  price="101">
			<title>Gone With The Wind</title>
			<author>Margaret</author>
		</book>
		<book id="0103"  price="101.5">
			<title>The Old Man And The Sea</title>
			<author>Hemingway</author>
		</book>
	</category>
	<category id="02" name="Economics">
		<book id="0201" price="50">
			<title>The Currency Wars</title>
			<author>Song</author>
		</book>
		<book id="0202" price="60">
			<title>Principle Of Economics</title>
			<author>Mankiw</author>
		</book>
	</category>
	<category id="03" name="Psychology">
		<book id="0301" price="40">
			<title>Psychology And Life</title>
			<author>Gerrig</author>
		</book>
		<book id="0302" price="45">
			<title>Social Psychology</title>
			<author>Miles</author>
		</book>	
	</category>	
</books>

Java解析XML

DOM4J

一次性读取整个XML文档,可以访问任意节点,适用于小型XML文档。

JAR

dom4j-1.6.1.jar

API

SAXReader类

read

Document doc = new SAXReader().read(inputStream);

由SAXReader对象读取指定的XML文件,获取Document类对象。


Document类

selectNodes / selectObject

List<Element> selectNodes(nodePath);

读取指定路径的元素,包括其所有子元素,返回一个树形结构的元素List。

两者虽然名字不同,但在我的使用过程中并未发现任何不同。

元素路径nodePath包含三类定义:

1.绝对路径:如"a/b/c",指向a->b->c元素。

2.查找路径:"//c",获取所有的c元素。

3.属性值过滤:如"//c[@id!=1]",获取所有id属性值不为1的c元素。


Element类

getName

String getName();

获取元素名。


attributeValue

String attributeValue(attributeName);

获取指定名称的属性值。


element

Element element(childNodeName);

获取指定名称的子元素对象。


elements

List<Element> elements();

获取所有子元素。


getText

String getText();

获取元素内的文本内容。


getPath

String getPath();

获取元素路径。


getParent

Element getParent();

获取父元素对象。


实例


如下是一个利用DOM4J对上文中的books.xml进行解析的实例。

public class TestDom4j {
	public static void main(String[] args) {
		SAXReader reader = new SAXReader();
		try {
			Document doc = reader.read(new FileInputStream("xml/books.xml"));
			List<Element> categories = (List<Element>) doc.selectNodes("//category");
			for (Element element : categories) {
				System.out.println(element.getName()+element.attributeValue("id")+":"+element.attributeValue("name"));
				List<Element> books = element.elements();
				for (Element element2 : books) {
					Element bookTitle = element2.element("title");
					Element bookAuthor = element2.element("author");
					String bookPrice = element2.attributeValue("price");
					System.out.println("\t<<"+bookTitle.getText()+">> by "+bookAuthor.getText()+" of $"+bookPrice);
				}
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (DocumentException e) {
			e.printStackTrace();
		}
	}
}


SAX

SAX(Simple API for XML),适用于大文件,从上至下解析。解析时多次读取,由事件驱动。

JAR

jaxen-1.1-beta-7.jar

限于篇幅,这里仅放出示例代码。

/**
 * SAX事件驱动解析方式
 * @author hsdsmljj
 *
 */
public class SAX_XML {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			//取得一个解析工厂实例
			SAXParserFactory factory=SAXParserFactory.newInstance();
			//得到解析器
			SAXParser parse=factory.newSAXParser();
			//开始解析[1:文件  2:事件]
			parse.parse("xml/books.xml", new ParseHandler());
			
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
}

/**
 * 定义一个默认事件驱动
 * @author hsdsmljj
 *
 */
class ParseHandler extends DefaultHandler{
	
	static int i=0;
	List<Book> books=new ArrayList<Book>();
	Book book;
	String bookAuthor="";
	String bookPrice="";
	String bookTitle="";
	String qName="";
	
	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attrs) throws SAXException {
		//如果在book元素的开始时
		if(qName.equals("book")){
			bookAuthor=attrs.getValue(0);
			bookPrice=attrs.getValue(1);
			book=new Book();
			book.setName(bookAuthor);
			book.setPrice(bookPrice);
		}
		//记录当前在解析哪个元素
		this.qName=qName;
	}
	
	@Override
	public void characters(char[] ch, int start, int length)
			throws SAXException {
		if(qName.equals("title") && book.getTitle()==null){
			System.out.println("============"+qName);
			book.setTitle(String.valueOf(ch, start, length));
		}
	}
	
	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		System.out.println("------"+this.bookTitle);
		//当book节点结束时就进行扫尾处理
		if(qName.equals("book")){
			books.add(book);
			this.bookAuthor="";
			this.bookPrice="";
			this.bookTitle="";
			this.qName="";
			book=null;
		}
		
	}
	
	//文档结束
	@Override
	public void endDocument() throws SAXException {
		for (Book book : books) {
			//自动调用toString方法
			System.out.println(book);
		}
	}

}


JS解析XML

由于XML与HTML同根同源,因此解析XML时与解析HTML并无太大区别,诸如getElementById、getElementsByTagName等均能直接使用于XML元素节点上。
区别在于HTML的载入在初始化时就自动进行,并且自动实例化了document对象,而对于XML则需要手动载入,生存文档对象。

function loadxml(xmlFile){
	var xmlDoc;
	if(window.ActiveXObject){
		//创建组件对象
		xmlDoc=new ActiveXObject('Microsoft.XMLDOM');
		//是否异步加载xml文件 如果为ture,程序不论xml文件是否全部载入就开始运行下面程序,所以如果接下来就操作xml文件可能出错 
		xmlDoc.async = false;
		//加载xml
		xmlDoc.load(xmlFile);  
	}else if(document.implementation && document.implementation.createDocument)   { 
		xmlDoc = document.implementation.createDocument('', '', null);   xmlDoc.load(xmlFile);  
	}else{  
		return null;  
	}  
	return xmlDoc;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值