SAX解析XMl文件

时间:2022-10-01 16:01:01

SAX解析XMl文件



   sax 是Simple API for XML的缩写,它并不是由W3C官方所提出的标准,可以说是“民间”的事实标准。
    SAX与DOM比较而言,SAX是一种轻量型的方法。
SAX在概念上与DOM完全不同。首先,不同于DOM的文档驱动,它是事件驱动的,也就是说,它并不需要读入整个文档,而文档的读入过程也就是SAX的解析过程。解析过程是这样的:在文档开始的时候调用startDocument(),在遇到节点调用startElement(),然后通过characters将节点的值读取出来在遇到节点结束时调用endElement(),文档结束时调用endDocument().在解析一个Xml文件的时候,我们需要一个处理器Hander,这个处理器继承DefaultHander,然后,我们还需要一个SAXParserFactory(解析工厂),由这个解析工厂拿到SAXParser,进行解析。。。。

现在我们来解析一个Xml文件,这个xml文件是servlet的配置文件,不想写xml文件了。。。。

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
<description>This is the description of my J2EE component</description>
<display-name>This is the display name of my J2EE component</display-name>
<servlet-name>TestServlet</servlet-name>
<servlet-class>com.wanjging.Servlet.TestServlet</servlet-class>
</servlet>
<servlet>
<description>This is the description of my J2EE component</description>
<display-name>This is the display name of my J2EE component</display-name>
<servlet-name>Demo1Servlet</servlet-name>
<servlet-class>com.wanjging.Servlet.Demo1Servlet</servlet-class>
</servlet>
<servlet>
<description>This is the description of my J2EE component</description>
<display-name>This is the display name of my J2EE component</display-name>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.wanjging.Servlet.LoginServlet</servlet-class>
</servlet>
<servlet>
<description>This is the description of my J2EE component</description>
<display-name>This is the display name of my J2EE component</display-name>
<servlet-name>HttpUtilsServlet</servlet-name>
<servlet-class>com.wanjging.Servlet.HttpUtilsServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>TestServlet</servlet-name>
<url-pattern>/servlet/TestServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Demo1Servlet</servlet-name>
<url-pattern>/servlet/Demo1Servlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/servlet/LoginServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>HttpUtilsServlet</servlet-name>
<url-pattern>/servlet/HttpUtilsServlet</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>

面向的对象的思想,对于每一个servlet节点,我们建立一个servlet实体类,对于解析出来的多个servlet,我们呢把它放在一个List中,以后循环输出。。。

servlet实体类:

<span style="color:#333333;">public class WebConfig {

private String description;
private String displayName;
private String servletName;
private String servletClass;

public WebConfig() {
super();
}
/**
* @return description
*/
public String getDescription() {
return description;
}
public WebConfig(String description, String displayName,
String servletName, String servletClass) {
super();
this.description = description;
this.displayName = displayName;
this.servletName = servletName;
this.servletClass = servletClass;
}
/**
* @param description 要设置的 description
*/
public void setDescription(String description) {
this.description = description;
}
/**
* @return displayName
*/
public String getDisplayName() {
return displayName;
}
/**
* @param displayName 要设置的 displayName
*/
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
/**
* @return servletName
*/
public String getServletName() {
return servletName;
}
/**
* @param servletName 要设置的 servletName
*/
public void setServletName(String servletName) {
this.servletName = servletName;
}
/**
* @return servletClass
*/
public String getServletClass() {
return servletClass;
}


/* (非 Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "WebConfig [description=" + description + ", displayName="
+ displayName + ", servletName=" + servletName
+ ", servletClass=" + servletClass + "]";
}
/**
* @param servletClass 要设置的 servletClass
*/
public void setServletClass(String servletClass) {
this.servletClass = servletClass;
}

}
</span>

现在我们就开始创建一个解析类,这个类需要继承DefaultHander

<span style="color:#333333;">class MyHandler extends DefaultHandler {

/**
* @return list
*/
public List<WebConfig> getList() {
return list;
}


private List<WebConfig> list = null;
private String tagName = null;
private WebConfig wc;
private final String description = "description";
private final String displayname = "display-name";
private final String servletname = "servlet-name";
private final String servletclass = "servlet-class";

@Override
public void startDocument() throws SAXException {
// 开始解析时,创建集合
list = new ArrayList<>();
System.out.println("开始文档节点");
super.startDocument();
}

// qName参数用来接收标签名
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {

if ("servlet".equals(qName)) {
System.out.println("开始标签");
wc = new WebConfig();
}

tagName = qName;

super.startElement(uri, localName, qName, attributes);
}

// 解析标签的内容传给了字节数组ch
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
super.characters(ch, start, length);
// 获取字节数据里面的数据
String tempStr = new String(ch, start, length);
if(tagName!=null){

switch (tagName) {
case description:
wc.setDescription(tempStr);
break;
case displayname:
wc.setDisplayName(tempStr);
break;
case servletname:
wc.setServletName(tempStr);
break;
case servletclass:
wc.setServletClass(tempStr);
break;

default:
break;
}
System.out.println("解析标签的数据内容");
}

}

//还是qName接收标签名
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
//结束标签后面的空格不会被忽略而被看成标签内容,就会调用characters方法
tagName=null;

if("servlet".equals(qName)){
list.add(wc);
}
System.out.println("结束标签");
super.endElement(uri, localName, qName);
}

@Override
public void endDocument() throws SAXException {
System.out.println("解析结束");
super.endDocument();
}
}</span>

最后我们来测试一下:

public class Test {
public static void main(String[] args) throws Exception, SAXException {
MyHandler handler = new MyHandler();
//创建解析工厂
SAXParserFactory factory = SAXParserFactory.newInstance();
//创建SAX解析器
SAXParser saxParser = factory.newSAXParser();
//xml文件读取流
InputStream xmlFileIs=new FileInputStream("filexml\\web.xml");

BufferedInputStream bis=new BufferedInputStream(xmlFileIs);

saxParser.parse(bis, handler);

List<WebConfig> list = handler.getList();

//遍历文件
for (WebConfig webConfig : list) {
System.out.println(webConfig.getDescription());
System.out.println(webConfig.getDisplayName());
System.out.println(webConfig.getServletClass());
System.out.println(webConfig.getServletName());
System.out.println();
}
}
}

解析的结果如下:

开始文档节点
解析标签的数据内容
开始标签
解析标签的数据内容
解析标签的数据内容
结束标签
解析标签的数据内容
结束标签
解析标签的数据内容
结束标签
解析标签的数据内容
结束标签
解析标签的数据内容
解析标签的数据内容
结束标签
解析标签的数据内容
结束标签
结束标签
结束标签
开始标签
解析标签的数据内容
解析标签的数据内容
结束标签
解析标签的数据内容
结束标签
解析标签的数据内容
结束标签
解析标签的数据内容
结束标签
结束标签
开始标签
解析标签的数据内容
解析标签的数据内容
结束标签
解析标签的数据内容
结束标签
解析标签的数据内容
结束标签
解析标签的数据内容
结束标签
结束标签
开始标签
解析标签的数据内容
解析标签的数据内容
结束标签
解析标签的数据内容
结束标签
解析标签的数据内容
结束标签
解析标签的数据内容
结束标签
结束标签
解析标签的数据内容
解析标签的数据内容
结束标签
解析标签的数据内容
结束标签
结束标签
解析标签的数据内容
解析标签的数据内容
结束标签
解析标签的数据内容
结束标签
结束标签
解析标签的数据内容
解析标签的数据内容
结束标签
解析标签的数据内容
结束标签
结束标签
解析标签的数据内容
解析标签的数据内容
结束标签
解析标签的数据内容
结束标签
结束标签
解析标签的数据内容
解析标签的数据内容
结束标签
结束标签
结束标签
解析结束


---------------------------------------
This is the description of my J2EE component
This is the display name of my J2EE component
com.wanjging.Servlet.TestServlet
TestServlet


---------------------------------------
This is the description of my J2EE component
This is the display name of my J2EE component
com.wanjging.Servlet.Demo1Servlet
Demo1Servlet


---------------------------------------
This is the description of my J2EE component
This is the display name of my J2EE component
com.wanjging.Servlet.LoginServlet
LoginServlet


---------------------------------------
This is the description of my J2EE component
This is the display name of my J2EE component
com.wanjging.Servlet.HttpUtilsServlet
HttpUtilsServlet


好啦,SAX,还是挺简单的。。。。。。