xml(一)

xml概述

xml标准文档的极佳版本

xml是一种能表示层次结构的标记语言,比属性文件的平面表结构更灵活,它与html较为类似

区别如下:

1.xml是大小写敏感的,如,

1
<H1>

1
<h1>

是不同的xml标签

2.在xml中,只有一个标签而无相应的尾标签的元素必须以/结尾,比如

1
<img src="" />

,这样,解析器就不必查找

1
</img>

标签了。

3.在xml中,属性值必须用引号括起来,在html中,引号是可有可无的,如

1
<applet code="" width=300 height=400>

对html来说是合法的,但对xml来说不合法。

4.在html中属性可以没有值,如,

1
<input type="radio" name="hhh" value="hhh" checked>

,在xml中所有属性都必须有值。

xml文档的结构

  1. xml应当以一个文档头开始,如:

    1
    <?xml version="1.0"  encoding="UTF-8"?>
  1. 文档头之后通常是文档类型定义,如:

    1
    <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DAD Web Application 2.2//EN" "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">
  2. 最后xml文档的正文包含根元素,根元素包含一些其他的元素。如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE configuration...>
    <configuration>
    <title>
    <font>
    <name>Helvetica</name>
    <size>36</size>
    </font>
    </title>
    </configuration>
  3. 元素可以有子元素、文本或者两者皆有(在设计xml文档时,最好使元素要么包含子元素,要么包含文本,应该避免以下情况:在xml规范中,这叫做混合式内容,避免了混合式内容可以简化简化解析过程。)

    1
    2
    3
    4
    <font>
    Helvetica
    <size>35</size>
    </font>
  4. 属性只应在修改值的解释时使用,而不是指定值时使用。

    元素和文档是xml文档的“主要支撑要素”,以下是一些标记说明

  5. 字符引用的形式是&#十进制值,或者&#x十六进制值,如字符e可以用下面两种形式表示: &#233; &#xD9;

  6. 实体引用的形式是&name;。下面这些实体引用:&lt;&gt;&amp;&quot;&apos;分别表示<,>,&,’,…等字符,可以在DTD中定义其他的实体引用。

  7. CDATA部分用<![CDATA[和]]>来限定其界限。他们是字符数据的一种特殊形式。你可以使用它们来包含那些含有<,>,&之类字符的字符串,而不必将它们解释为标记,例如:

1
<![CDATA[< & > are myfavourate delimiters]]>

CDATA部分不能包含字符串]]>。使用这一特性时要特别注意。它常用来当做将传统数据偷偷纳入XML文档的一个后门。

  1. 处理指令(processing instruction)是那些专门在处理xml文档的应用程序中使用的指令,它们将用<?和?>来限定其界限,例如:
1
<?xml-stylesheet href="mystyle.css" type="text/css"?>

每个xml都以下面这个处理指令开头:

<?xml version=”1.0” encoding=”utf-8”?>

  1. 注释用<!– 和–!>来限定其界限:<!– 这是一个注释 –!>

解析xml文档

一、基于文档对象模型(DOM)的树形解析器

DOM解析器对于实现我们的大多数目的来说都很容易,不过用它生成树结构会消耗大量内存。JDK中自己包含的有DOM解析器,我们可以直接拿来用

下面的代码使用了DOM解析器解析了相关的xml文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package domtree;

import java.io.File;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;

public class Main {

public static void main(String[] args) {
// TODO Auto-generated method stub
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();//DocumentBuilderFactory实例化
File file=new File("src/web.xml");//classpath下的一个xml文件
try {
DocumentBuilder builder=factory.newDocumentBuilder();
Document doc=builder.parse(file);//选择输入源,可以是文件或者是URL:
//Document doc=builder.parse(url);或者是一个输入流:
//Document doc=builder.parse(inputStream);
//如果使用输入流作为输入源,当这个源的初始化对象是那些相对于文档位置定位的文件时
//解析器将无法定位,但是可以通过安装一个“实体分解器(entity resolver)”
//来解决这个问题
Element root =doc.getDocumentElement();//获得根节点
treeParser("",root);//递归的访问元素节点
//System.out.println("hhhh\thhhh");测试tab
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}
public static void treeParser(String tab,Element element){
System.out.println(tab+element.getTagName());//打印元素节点名称
NodeList childrens=element.getChildNodes();//获得元素节点的所有子节点
if(childrens.getLength()>1){//若元素节点的子节点还有元素节点
for(int i=0;i<childrens.getLength();i++){//遍历element的所有子节点
Node child=childrens.item(i);
if(child instanceof Element){//若其是元素节点,则递归的访问其子节点
treeParser(tab+"\t",(Element)child);
}
}
}else{//element元素节点下只剩数据,则输出其数据
System.out.print(tab+"\t");
System.out.println(
((Text)element.getFirstChild())
.getData().trim());//

}
System.out.println(tab+element.getTagName());//再次输出元素节点名称
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">

<!--
配置 org.springframework.web.filter.HiddenHttpMethodFilter: 可以把 POST 请求转为 DELETE 或 POST 请求
-->
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>

<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<!-- 配置 DispatcherServlet -->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 配置 DispatcherServlet 的一个初始化参数: 配置 SpringMVC 配置文件的位置和名称 -->
<!--
实际上也可以不通过 contextConfigLocation 来配置 SpringMVC 的配置文件, 而使用默认的.
默认的配置文件为: /WEB-INF/<servlet-name>-servlet.xml
-->

<!-- <init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param> -->

<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

</web-app>

运行结果

二、基于xml简单API的(SAX)的流机制解析器(事件回调方式)

SAX解析器在解析XML输入的控件时就报告事件,但不会以任何方式存储文档。

在使用SAX解析器时,需要一个处理器来定义不同的解析器事件的事件动作。他们都实现了ContentHandler接口。ContentHandler接口定义了几个回调方法。最常用的如下

  • startElement和endElement在每当遇到起始或终止标签是调用。
  • characters每当遇到字符数据时调用。
  • startDocument和endDocument分别在文档开始和结束时各调用一次。

例如解析以下片段时:

1
2
3
4
<font>
<name>Helvetica</name>
<size units="pt">36</size>
</font>

解析器会有以下调用:

  1. startElement,元素名:font
  2. startElement,元素名:name
  3. characters,内容:Helvetica
  4. endElement,元素名:name
  5. startElement,元素名:size,属性:units=“pt”
  6. characters,内容:36
  7. endElement,元素名:size
  8. endElement,元素名:font

示例程序如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package saxtest;

import java.io.InputStream;
import java.net.URL;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.helpers.DefaultHandler;

public class SAXTest
{
public static void main(String[] args) throws Exception
{
String url;
if (args.length == 0)
{
url = "http://www.w3c.org";
System.out.println("Using " + url);
}
else url = args[0];

DefaultHandler handler = new DefaultHandler()//用匿名内部类实例化处理器
{
public void startElement(String namespaceURI, String lname, String qname,
Attributes attrs)
{
//namespaceURL:命名空间
//lname:本地名
//qname:以alias:localname形式表示的限定名
//attrs:元素属性集合
if (lname.equals("a") && attrs != null)
{
for (int i = 0; i < attrs.getLength(); i++)//对属性集合遍历
{
String aname = attrs.getLocalName(i);//获得属性的本地名
if (aname.equals("href"))
System.out.println(attrs.getValue(i));
//打印输出属性值
}
}
}
};

SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(true);//设置命名空间可用
SAXParser saxParser = factory.newSAXParser();//获取SAX解析器
InputStream in = new URL(url).openStream();//获得输入流
saxParser.parse(in, handler);
//根据传入的输入流(可以是文件,URL等)和处理器来处理xml文件
//处理器必须是DefaultHandler的子类,DefaultHandler类为以下接口定义了空的方法:
//ContentHandler,DTDHandler,EntityResolver,ErrorHandler
}
}

这是运行结果

Donate comment here