SAX方式解析XML文件的方法分析,并取特定字段生成对象
2017-10-30 13:58
639 查看
SAX(Simple API for XML)SAX的工作原理简单地说就是对文档进行顺序扫描,当扫描到文档(document)开始与结束、元素(element)开始与结束、文档(document)结束等地方时通知事件处理方法,由事件处理函数做相应动作,然后继续同样的扫描,直至文档结束。SAX解析方式适用于大型文档,因为他的解析是逐行进行不用像DOM中那样为所有节点创建对象,这样效率大大提高,所以虽然它不是W3C标准,但它却得到了广泛认可。
1,这是需要解析的XML
<?xml version="1.0" encoding="UTF-8"?>
<packet className="" type="字符串定长报文">
<reference name="报文头" referenceFile="service/bizservice/host/head/snd_host_head1.packet"/>
<category name="body">
<field fieldDefaultValue="""" fieldDescription="省代码" fieldName="PROVINCECODE" fieldSubtle="false" fieldType="String" fieldValidation="false">
<valueExpr expr="PROVINCECODE"/>
<method className="StringMethod" methodName="fill">
<parameter name="fillchar" type="string" value="0"/>
<parameter name="len" type="int" value="2"/>
<parameter name="dir" type="string" value="左边"/>
</method>
<parameter name="位置" value="-1"/>
<parameter name="偏移量" value="0"/>
<parameter name="数据格式" value=
4000
"9(2)"/>
</field>
<field fieldDefaultValue="""" fieldDescription="旧账号" fieldName="OLDACCTNO" fieldSubtle="false" fieldType="String" fieldValidation="false">
<valueExpr expr="OLDACCTNO"/>
<method className="StringMethod" methodName="fill">
<parameter name="fillchar" type="string" value=" "/>
<parameter name="len" type="int" value="23"/>
<parameter name="dir" type="string" value="右边"/>
</method>
<parameter name="位置" value="-1"/>
<parameter name="偏移量" value="0"/>
<parameter name="数据格式" value="X(23)"/>
</field>
<field fieldDefaultValue="""" fieldDescription="偏移量(界面隐藏)" fieldName="OFFSETPOS" fieldSubtle="false" fieldType="String" fieldValidation="false">
<valueExpr expr="OFFSETPOS"/>
<parameter name="位置" value="-1"/>
<parameter name="偏移量" value="0"/>
<parameter name="数据格式" value="9(3)"/>
</field>
<field fieldDefaultValue="""" fieldDescription="账号" fieldName="ACCTNO" fieldSubtle="false" fieldType="String" fieldValidation="false">
<valueExpr expr="ACCTNO"/>
<parameter name="位置" value="-1"/>
<parameter name="偏移量" value="0"/>
<parameter name="数据格式" value="9(17)"/>
</field>
<field fieldDefaultValue="""" fieldDescription="子账户类型" fieldName="SUBACCTTYPE" fieldSubtle="false" fieldType="String" fieldValidation="false">
<valueExpr expr="SUBACCTTYPE"/>
<parameter name="位置" value="-1"/>
<parameter name="偏移量" value="0"/>
<parameter name="数据格式" value="X(4)"/>
</field>
<field fieldDefaultValue="""" fieldDescription="册号" fieldName="VOLUMENO" fieldSubtle="false" fieldType="String" fieldValidation="false">
<valueExpr expr="VOLUMENO"/>
<method className="StringMethod" methodName="fill">
<parameter name="fillchar" type="string" value="0"/>
<parameter name="len" type="int" value="3"/>
<parameter name="dir" type="string" value="左边"/>
</method>
<parameter name="位置" value="-1"/>
<parameter name="偏移量" value="0"/>
<parameter name="数据格式" value="9(3)"/>
</field>
<field fieldDefaultValue="""" fieldDescription="序号" fieldName="SEQNO" fieldSubtle="false" fieldType="String" fieldValidation="false">
<valueExpr expr="SEQNO"/>
<method className="StringMethod" methodName="fill">
<parameter name="fillchar" type="string" value="0"/>
<parameter name="len" type="int" value="2"/>
<parameter name="dir" type="string" value="左边"/>
</method>
<parameter name="位置" value="-1"/>
<parameter name="偏移量" value="0"/>
<parameter name="数据格式" value="9(2)"/>
</field>
<field fieldDefaultValue="""" fieldDescription="功能选项" fieldName="FunctionalOption" fieldSubtle="false" fieldType="String" fieldValidation="false">
<valueExpr expr="FunctionalOption"/>
<method className="StringMethod" methodName="fill">
<parameter name="fillchar" type="string" value=" "/>
<parameter name="len" type="int" value="1"/>
<parameter name="dir" type="string" value="右边"/>
</method>
<parameter name="位置" value="-1"/>
<parameter name="偏移量" value="0"/>
<parameter name="数据格式" value="X"/>
</field>
<field fieldDefaultValue="""" fieldDescription="FILLER" fieldName="FILLER" fieldSubtle="false" fieldType="String" fieldValidation="false">
<valueExpr expr="FILLER"/>
<parameter name="位置" value="-1"/>
<parameter name="偏移量" value="0"/>
<parameter name="数据格式" value="9"/>
</field>
<field fieldDefaultValue="""" fieldDescription="FILLER" fieldName="FILLER" fieldSubtle="false" fieldType="String" fieldValidation="false">
<valueExpr expr="FILLER"/>
<parameter name="位置" value="-1"/>
<parameter name="偏移量" value="0"/>
<parameter name="数据格式" value="9"/>
</field>
<field fieldDefaultValue="""" fieldDescription="FILLER" fieldName="FILLER" fieldSubtle="false" fieldType="String" fieldValidation="false">
<valueExpr expr="FILLER"/>
<method className="StringMethod" methodName="fill">
<parameter name="fillchar" type="string" value=" "/>
<parameter name="len" type="int" value="34"/>
<parameter name="dir" type="string" value="右边"/>
</method>
<parameter name="位置" value="-1"/>
<parameter name="偏移量" value="0"/>
<parameter name="数据格式" value="X(34)"/>
</field>
<field fieldDefaultValue="""" fieldDescription="FILLER" fieldName="FILLER" fieldSubtle="false" fieldType="String" fieldValidation="false">
<valueExpr expr="FILLER"/>
<method className="StringMethod" methodName="fill">
<parameter name="fillchar" type="string" value=" "/>
<parameter name="len" type="int" value="2"/>
<parameter name="dir" type="string" value="右边"/>
</method>
<parameter name="位置" value="-1"/>
<parameter name="偏移量" value="0"/>
<parameter name="数据格式" value="X(2)"/>
</field>
<field fieldDefaultValue="""" fieldDescription="旧帐号标识" fieldName="OLDFLAG" fieldType="String">
<valueExpr expr="OLDFLAG"/>
<method className="StringMethod" methodName="fill">
<parameter name="fillchar" type="string" value="0"/>
<parameter name="len" type="int" value="2"/>
<parameter name="dir" type="string" value="左边"/>
</method>
<parameter name="位置" value="-1"/>
<parameter name="偏移量" value="0"/>
<parameter name="数据格式" value="9(2)"/>
</field>
</category>
<parameter name="编码" value="GBK"/>
<reference name="报文尾" referenceFile="service/bizservice/host/head/snd_host_head2.packet"/>
</packet>
2,DefaultHandler类是SAX2事件处理程序的默认基类。它实现了EntityResolver、DTDHandler、ContentHandler和ErrorHandler这四个接口。包含这四个接口的所有方法,所以我们在编写事件处理程序时,可以不用直接实现这四个接口,而继承该类,然后重写我们需要的方法即可
我们SAX方法解析XML文件时需要一个Handler类来提供解析的方法,里面包含了重写的继承于DefaultHandler类的两种方法,分别有开始和结束的方法
package socket.msg.pack;
import java.util.ArrayList;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import socket.msg.MsgField;
import socket.msg.MsgField.FillSide;
public class SAXParserHandler extends DefaultHandler {
int bookIndex = 0;
private ArrayList<String> nameList = new ArrayList<>();
private ArrayList<String> fillList = new ArrayList<>();
private ArrayList<String> dataList = new ArrayList<>();
public ArrayList<String> getNameList() {
return nameList;
}
public ArrayList<String> getFillList() {
return fillList;
}
public ArrayList<String> getDataList() {
return dataList;
}
// 用来标识解析开始和结束
@Override
public void startDocument() throws SAXException {
super.startDocument();
System.out.println("SAX解析开始");
}
@Override
public void endDocument() throws SAXException {
super.startDocument();
System.out.println("SAX解析结束");
}
// 用来遍历XML文件的开始标签
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes);
// 开始解析field节点的属性
if (qName.equals("field")) {
bookIndex++;
int len = attributes.getLength();
System.out.println("*************************开始遍历第" + (bookIndex) + "个Field*************************");
for (int i = 0; i < len; i++) {
if (attributes.getQName(i).equals("fieldName")) {
// field.setName(attributes.getValue(i));
nameList.add(attributes.getValue(i));
System.out.println(attributes.getQName(i) + ":" + attributes.getValue(i));
}
}
}
// 获取field节点的所有子节点节点名
if (qName.equals("parameter")) {
if ("fillchar".equals(attributes.getValue("name"))||"偏移量".equals(attributes.getValue("name"))) {
fillList.add(attributes.getValue("value"));
}
if ("数据格式".equals(attributes.getValue("name"))) {
dataList.add(attributes.getValue("value"));
}
System.out.println(attributes.getValue("name") + ":" + attributes.getValue("value"));
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
super.endElement(uri, localName, qName);
// 判断针对是否已经遍历结束
if (qName.equals("field")) {
System.out.println("===========================结束遍历===========================");
}
}
}
3,Handler类准备好之后我们来编写测试程序看一下解析结果:
package socket.msg.pack;
import java.io.IOException;
import java.util.ArrayList;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.SAXException;
import socket.msg.pack.SAXParserHandler;
import socket.msg.MsgField;
import socket.msg.MsgField.FillSide;
public class TestSAX {
public static void main(String[] args) throws ParserConfigurationException, SAXException {
try {
// 是创建一个Handler处理类,去逐个分析每一个节点,并且是顺序的
// 1.通过SAXParseFactory的静态方法newInstance()来获取SAXParseFactory的实例对象factory
SAXParserFactory factory = SAXParserFactory.newInstance();
// 2.通过SAXParserFactory 静态方法NewSAXParser()方法返回一个SAXParser类的实例;
SAXParserHandler handler = new SAXParserHandler();
// 3.重写startElement、endElement、startDocument、endDocument方法
/*
* 可以将其保存在继承了DefaultHandler类的SAXParserHandler类中
* 然后创建SAXParserHandler类的对象并将其传入SAXParser类的对象parser的parser方法;
*/
SAXParser parser = factory.newSAXParser();
String name=null;
int length = 0;
char fillChar=0;
FillSide fillSide = null;
parser.parse("D:\\request.packet", handler);
ArrayList<String> nameList = new ArrayList<>();
ArrayList<String> fillList = new ArrayList<>();
ArrayList<String> dataList = new ArrayList<>();
nameList = handler.getNameList();
fillList=handler.getFillList();
dataList=handler.getDataList();
for (int i = 0; i < nameList.size(); i++) {
name = nameList.get(i);
fillChar = fillList.get(i).charAt(0);
String s = dataList.get(i);
if (s.length() == 1) {
fillSide=getDirection(s);
} else {
String [] ss = s.split("\\(");
fillSide=getDirection(ss[0]);
length = Integer.parseInt(ss[1].substring(0, ss[1].length() - 1));
}
MsgField field = new MsgField(name, length, fillChar, fillSide);
System.out.println(field);
}
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static FillSide getDirection(String s) {
FillSide fillSide = null;
if ("X".equals(s)) {
fillSide = FillSide.RIGHT;
} else if ("9".equals(s)) {
fillSide = FillSide.LEFT;
}
return fillSide;
}
}
4,以下是解析结果
SAX解析开始
*************************开始遍历第1个Field*************************
fieldName:PROVINCECODE
fillchar:0
len:2
dir:左边
位置:-1
偏移量:0
数据格式:9(2)
===========================结束遍历===========================
*************************开始遍历第2个Field*************************
fieldName:OLDACCTNO
fillchar:
len:23
dir:右边
位置:-1
偏移量:0
数据格式:X(23)
===========================结束遍历===========================
*************************开始遍历第3个Field*************************
fieldName:OFFSETPOS
位置:-1
偏移量:0
数据格式:9(3)
===========================结束遍历===========================
*************************开始遍历第4个Field*************************
fieldName:ACCTNO
位置:-1
偏移量:0
数据格式:9(17)
===========================结束遍历===========================
*************************开始遍历第5个Field*************************
fieldName:SUBACCTTYPE
位置:-1
偏移量:0
数据格式:X(4)
===========================结束遍历===========================
*************************开始遍历第6个Field*************************
fieldName:VOLUMENO
fillchar:0
len:3
dir:左边
位置:-1
偏移量:0
数据格式:9(3)
===========================结束遍历===========================
*************************开始遍历第7个Field*************************
fieldName:SEQNO
fillchar:0
len:2
dir:左边
位置:-1
偏移量:0
数据格式:9(2)
===========================结束遍历===========================
*************************开始遍历第8个Field*************************
fieldName:FunctionalOption
fillchar:
len:1
dir:右边
位置:-1
偏移量:0
数据格式:X
===========================结束遍历===========================
*************************开始遍历第9个Field*************************
fieldName:FILLER
位置:-1
偏移量:0
数据格式:9
===========================结束遍历===========================
*************************开始遍历第10个Field*************************
fieldName:FILLER
位置:-1
偏移量:0
数据格式:9
===========================结束遍历===========================
*************************开始遍历第11个Field*************************
fieldName:FILLER
fillchar:
len:34
dir:右边
位置:-1
偏移量:0
数据格式:X(34)
===========================结束遍历===========================
*************************开始遍历第12个Field*************************
fieldName:FILLER
fillchar:
len:2
dir:右边
位置:-1
偏移量:0
数据格式:X(2)
===========================结束遍历===========================
*************************开始遍历第13个Field*************************
fieldName:OLDFLAG
fillchar:0
len:2
dir:左边
位置:-1
偏移量:0
数据格式:9(2)
===========================结束遍历===========================
编码:GBK
SAX解析结束
MsgField [name=PROVINCECODE, length=2, fillChar=0, fillSide=LEFT]
MsgField [name=OLDACCTNO, length=23, fillChar=0, fillSide=RIGHT]
MsgField [name=OFFSETPOS, length=3, fillChar= , fillSide=LEFT]
MsgField [name=ACCTNO, length=17, fillChar=0, fillSide=LEFT]
MsgField [name=SUBACCTTYPE, length=4, fillChar=0, fillSide=RIGHT]
MsgField [name=VOLUMENO, length=3, fillChar=0, fillSide=LEFT]
MsgField [name=SEQNO, length=2, fillChar=0, fillSide=LEFT]
MsgField [name=FunctionalOption, length=2, fillChar=0, fillSide=RIGHT]
MsgField [name=FILLER, length=2, fillChar=0, fillSide=LEFT]
MsgField [name=FILLER, length=2, fillChar=0, fillSide=LEFT]
MsgField [name=FILLER, length=34, fillChar=0, fillSide=RIGHT]
MsgField [name=FILLER, length=2, fillChar= , fillSide=RIGHT]
MsgField [name=OLDFLAG, length=2, fillChar=0, fillSide=LEFT]
1,这是需要解析的XML
<?xml version="1.0" encoding="UTF-8"?>
<packet className="" type="字符串定长报文">
<reference name="报文头" referenceFile="service/bizservice/host/head/snd_host_head1.packet"/>
<category name="body">
<field fieldDefaultValue="""" fieldDescription="省代码" fieldName="PROVINCECODE" fieldSubtle="false" fieldType="String" fieldValidation="false">
<valueExpr expr="PROVINCECODE"/>
<method className="StringMethod" methodName="fill">
<parameter name="fillchar" type="string" value="0"/>
<parameter name="len" type="int" value="2"/>
<parameter name="dir" type="string" value="左边"/>
</method>
<parameter name="位置" value="-1"/>
<parameter name="偏移量" value="0"/>
<parameter name="数据格式" value=
4000
"9(2)"/>
</field>
<field fieldDefaultValue="""" fieldDescription="旧账号" fieldName="OLDACCTNO" fieldSubtle="false" fieldType="String" fieldValidation="false">
<valueExpr expr="OLDACCTNO"/>
<method className="StringMethod" methodName="fill">
<parameter name="fillchar" type="string" value=" "/>
<parameter name="len" type="int" value="23"/>
<parameter name="dir" type="string" value="右边"/>
</method>
<parameter name="位置" value="-1"/>
<parameter name="偏移量" value="0"/>
<parameter name="数据格式" value="X(23)"/>
</field>
<field fieldDefaultValue="""" fieldDescription="偏移量(界面隐藏)" fieldName="OFFSETPOS" fieldSubtle="false" fieldType="String" fieldValidation="false">
<valueExpr expr="OFFSETPOS"/>
<parameter name="位置" value="-1"/>
<parameter name="偏移量" value="0"/>
<parameter name="数据格式" value="9(3)"/>
</field>
<field fieldDefaultValue="""" fieldDescription="账号" fieldName="ACCTNO" fieldSubtle="false" fieldType="String" fieldValidation="false">
<valueExpr expr="ACCTNO"/>
<parameter name="位置" value="-1"/>
<parameter name="偏移量" value="0"/>
<parameter name="数据格式" value="9(17)"/>
</field>
<field fieldDefaultValue="""" fieldDescription="子账户类型" fieldName="SUBACCTTYPE" fieldSubtle="false" fieldType="String" fieldValidation="false">
<valueExpr expr="SUBACCTTYPE"/>
<parameter name="位置" value="-1"/>
<parameter name="偏移量" value="0"/>
<parameter name="数据格式" value="X(4)"/>
</field>
<field fieldDefaultValue="""" fieldDescription="册号" fieldName="VOLUMENO" fieldSubtle="false" fieldType="String" fieldValidation="false">
<valueExpr expr="VOLUMENO"/>
<method className="StringMethod" methodName="fill">
<parameter name="fillchar" type="string" value="0"/>
<parameter name="len" type="int" value="3"/>
<parameter name="dir" type="string" value="左边"/>
</method>
<parameter name="位置" value="-1"/>
<parameter name="偏移量" value="0"/>
<parameter name="数据格式" value="9(3)"/>
</field>
<field fieldDefaultValue="""" fieldDescription="序号" fieldName="SEQNO" fieldSubtle="false" fieldType="String" fieldValidation="false">
<valueExpr expr="SEQNO"/>
<method className="StringMethod" methodName="fill">
<parameter name="fillchar" type="string" value="0"/>
<parameter name="len" type="int" value="2"/>
<parameter name="dir" type="string" value="左边"/>
</method>
<parameter name="位置" value="-1"/>
<parameter name="偏移量" value="0"/>
<parameter name="数据格式" value="9(2)"/>
</field>
<field fieldDefaultValue="""" fieldDescription="功能选项" fieldName="FunctionalOption" fieldSubtle="false" fieldType="String" fieldValidation="false">
<valueExpr expr="FunctionalOption"/>
<method className="StringMethod" methodName="fill">
<parameter name="fillchar" type="string" value=" "/>
<parameter name="len" type="int" value="1"/>
<parameter name="dir" type="string" value="右边"/>
</method>
<parameter name="位置" value="-1"/>
<parameter name="偏移量" value="0"/>
<parameter name="数据格式" value="X"/>
</field>
<field fieldDefaultValue="""" fieldDescription="FILLER" fieldName="FILLER" fieldSubtle="false" fieldType="String" fieldValidation="false">
<valueExpr expr="FILLER"/>
<parameter name="位置" value="-1"/>
<parameter name="偏移量" value="0"/>
<parameter name="数据格式" value="9"/>
</field>
<field fieldDefaultValue="""" fieldDescription="FILLER" fieldName="FILLER" fieldSubtle="false" fieldType="String" fieldValidation="false">
<valueExpr expr="FILLER"/>
<parameter name="位置" value="-1"/>
<parameter name="偏移量" value="0"/>
<parameter name="数据格式" value="9"/>
</field>
<field fieldDefaultValue="""" fieldDescription="FILLER" fieldName="FILLER" fieldSubtle="false" fieldType="String" fieldValidation="false">
<valueExpr expr="FILLER"/>
<method className="StringMethod" methodName="fill">
<parameter name="fillchar" type="string" value=" "/>
<parameter name="len" type="int" value="34"/>
<parameter name="dir" type="string" value="右边"/>
</method>
<parameter name="位置" value="-1"/>
<parameter name="偏移量" value="0"/>
<parameter name="数据格式" value="X(34)"/>
</field>
<field fieldDefaultValue="""" fieldDescription="FILLER" fieldName="FILLER" fieldSubtle="false" fieldType="String" fieldValidation="false">
<valueExpr expr="FILLER"/>
<method className="StringMethod" methodName="fill">
<parameter name="fillchar" type="string" value=" "/>
<parameter name="len" type="int" value="2"/>
<parameter name="dir" type="string" value="右边"/>
</method>
<parameter name="位置" value="-1"/>
<parameter name="偏移量" value="0"/>
<parameter name="数据格式" value="X(2)"/>
</field>
<field fieldDefaultValue="""" fieldDescription="旧帐号标识" fieldName="OLDFLAG" fieldType="String">
<valueExpr expr="OLDFLAG"/>
<method className="StringMethod" methodName="fill">
<parameter name="fillchar" type="string" value="0"/>
<parameter name="len" type="int" value="2"/>
<parameter name="dir" type="string" value="左边"/>
</method>
<parameter name="位置" value="-1"/>
<parameter name="偏移量" value="0"/>
<parameter name="数据格式" value="9(2)"/>
</field>
</category>
<parameter name="编码" value="GBK"/>
<reference name="报文尾" referenceFile="service/bizservice/host/head/snd_host_head2.packet"/>
</packet>
2,DefaultHandler类是SAX2事件处理程序的默认基类。它实现了EntityResolver、DTDHandler、ContentHandler和ErrorHandler这四个接口。包含这四个接口的所有方法,所以我们在编写事件处理程序时,可以不用直接实现这四个接口,而继承该类,然后重写我们需要的方法即可
我们SAX方法解析XML文件时需要一个Handler类来提供解析的方法,里面包含了重写的继承于DefaultHandler类的两种方法,分别有开始和结束的方法
package socket.msg.pack;
import java.util.ArrayList;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import socket.msg.MsgField;
import socket.msg.MsgField.FillSide;
public class SAXParserHandler extends DefaultHandler {
int bookIndex = 0;
private ArrayList<String> nameList = new ArrayList<>();
private ArrayList<String> fillList = new ArrayList<>();
private ArrayList<String> dataList = new ArrayList<>();
public ArrayList<String> getNameList() {
return nameList;
}
public ArrayList<String> getFillList() {
return fillList;
}
public ArrayList<String> getDataList() {
return dataList;
}
// 用来标识解析开始和结束
@Override
public void startDocument() throws SAXException {
super.startDocument();
System.out.println("SAX解析开始");
}
@Override
public void endDocument() throws SAXException {
super.startDocument();
System.out.println("SAX解析结束");
}
// 用来遍历XML文件的开始标签
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes);
// 开始解析field节点的属性
if (qName.equals("field")) {
bookIndex++;
int len = attributes.getLength();
System.out.println("*************************开始遍历第" + (bookIndex) + "个Field*************************");
for (int i = 0; i < len; i++) {
if (attributes.getQName(i).equals("fieldName")) {
// field.setName(attributes.getValue(i));
nameList.add(attributes.getValue(i));
System.out.println(attributes.getQName(i) + ":" + attributes.getValue(i));
}
}
}
// 获取field节点的所有子节点节点名
if (qName.equals("parameter")) {
if ("fillchar".equals(attributes.getValue("name"))||"偏移量".equals(attributes.getValue("name"))) {
fillList.add(attributes.getValue("value"));
}
if ("数据格式".equals(attributes.getValue("name"))) {
dataList.add(attributes.getValue("value"));
}
System.out.println(attributes.getValue("name") + ":" + attributes.getValue("value"));
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
super.endElement(uri, localName, qName);
// 判断针对是否已经遍历结束
if (qName.equals("field")) {
System.out.println("===========================结束遍历===========================");
}
}
}
3,Handler类准备好之后我们来编写测试程序看一下解析结果:
package socket.msg.pack;
import java.io.IOException;
import java.util.ArrayList;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.SAXException;
import socket.msg.pack.SAXParserHandler;
import socket.msg.MsgField;
import socket.msg.MsgField.FillSide;
public class TestSAX {
public static void main(String[] args) throws ParserConfigurationException, SAXException {
try {
// 是创建一个Handler处理类,去逐个分析每一个节点,并且是顺序的
// 1.通过SAXParseFactory的静态方法newInstance()来获取SAXParseFactory的实例对象factory
SAXParserFactory factory = SAXParserFactory.newInstance();
// 2.通过SAXParserFactory 静态方法NewSAXParser()方法返回一个SAXParser类的实例;
SAXParserHandler handler = new SAXParserHandler();
// 3.重写startElement、endElement、startDocument、endDocument方法
/*
* 可以将其保存在继承了DefaultHandler类的SAXParserHandler类中
* 然后创建SAXParserHandler类的对象并将其传入SAXParser类的对象parser的parser方法;
*/
SAXParser parser = factory.newSAXParser();
String name=null;
int length = 0;
char fillChar=0;
FillSide fillSide = null;
parser.parse("D:\\request.packet", handler);
ArrayList<String> nameList = new ArrayList<>();
ArrayList<String> fillList = new ArrayList<>();
ArrayList<String> dataList = new ArrayList<>();
nameList = handler.getNameList();
fillList=handler.getFillList();
dataList=handler.getDataList();
for (int i = 0; i < nameList.size(); i++) {
name = nameList.get(i);
fillChar = fillList.get(i).charAt(0);
String s = dataList.get(i);
if (s.length() == 1) {
fillSide=getDirection(s);
} else {
String [] ss = s.split("\\(");
fillSide=getDirection(ss[0]);
length = Integer.parseInt(ss[1].substring(0, ss[1].length() - 1));
}
MsgField field = new MsgField(name, length, fillChar, fillSide);
System.out.println(field);
}
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static FillSide getDirection(String s) {
FillSide fillSide = null;
if ("X".equals(s)) {
fillSide = FillSide.RIGHT;
} else if ("9".equals(s)) {
fillSide = FillSide.LEFT;
}
return fillSide;
}
}
4,以下是解析结果
SAX解析开始
*************************开始遍历第1个Field*************************
fieldName:PROVINCECODE
fillchar:0
len:2
dir:左边
位置:-1
偏移量:0
数据格式:9(2)
===========================结束遍历===========================
*************************开始遍历第2个Field*************************
fieldName:OLDACCTNO
fillchar:
len:23
dir:右边
位置:-1
偏移量:0
数据格式:X(23)
===========================结束遍历===========================
*************************开始遍历第3个Field*************************
fieldName:OFFSETPOS
位置:-1
偏移量:0
数据格式:9(3)
===========================结束遍历===========================
*************************开始遍历第4个Field*************************
fieldName:ACCTNO
位置:-1
偏移量:0
数据格式:9(17)
===========================结束遍历===========================
*************************开始遍历第5个Field*************************
fieldName:SUBACCTTYPE
位置:-1
偏移量:0
数据格式:X(4)
===========================结束遍历===========================
*************************开始遍历第6个Field*************************
fieldName:VOLUMENO
fillchar:0
len:3
dir:左边
位置:-1
偏移量:0
数据格式:9(3)
===========================结束遍历===========================
*************************开始遍历第7个Field*************************
fieldName:SEQNO
fillchar:0
len:2
dir:左边
位置:-1
偏移量:0
数据格式:9(2)
===========================结束遍历===========================
*************************开始遍历第8个Field*************************
fieldName:FunctionalOption
fillchar:
len:1
dir:右边
位置:-1
偏移量:0
数据格式:X
===========================结束遍历===========================
*************************开始遍历第9个Field*************************
fieldName:FILLER
位置:-1
偏移量:0
数据格式:9
===========================结束遍历===========================
*************************开始遍历第10个Field*************************
fieldName:FILLER
位置:-1
偏移量:0
数据格式:9
===========================结束遍历===========================
*************************开始遍历第11个Field*************************
fieldName:FILLER
fillchar:
len:34
dir:右边
位置:-1
偏移量:0
数据格式:X(34)
===========================结束遍历===========================
*************************开始遍历第12个Field*************************
fieldName:FILLER
fillchar:
len:2
dir:右边
位置:-1
偏移量:0
数据格式:X(2)
===========================结束遍历===========================
*************************开始遍历第13个Field*************************
fieldName:OLDFLAG
fillchar:0
len:2
dir:左边
位置:-1
偏移量:0
数据格式:9(2)
===========================结束遍历===========================
编码:GBK
SAX解析结束
MsgField [name=PROVINCECODE, length=2, fillChar=0, fillSide=LEFT]
MsgField [name=OLDACCTNO, length=23, fillChar=0, fillSide=RIGHT]
MsgField [name=OFFSETPOS, length=3, fillChar= , fillSide=LEFT]
MsgField [name=ACCTNO, length=17, fillChar=0, fillSide=LEFT]
MsgField [name=SUBACCTTYPE, length=4, fillChar=0, fillSide=RIGHT]
MsgField [name=VOLUMENO, length=3, fillChar=0, fillSide=LEFT]
MsgField [name=SEQNO, length=2, fillChar=0, fillSide=LEFT]
MsgField [name=FunctionalOption, length=2, fillChar=0, fillSide=RIGHT]
MsgField [name=FILLER, length=2, fillChar=0, fillSide=LEFT]
MsgField [name=FILLER, length=2, fillChar=0, fillSide=LEFT]
MsgField [name=FILLER, length=34, fillChar=0, fillSide=RIGHT]
MsgField [name=FILLER, length=2, fillChar= , fillSide=RIGHT]
MsgField [name=OLDFLAG, length=2, fillChar=0, fillSide=LEFT]
相关文章推荐
- SAX方式解析XML文件的方法分析
- DOM方式解析XML文件的方法分析
- Java生成和解析XML格式文件和字符串的实例代码【dom4j中的SAXReader对象读取并解析xml文件】
- 【Android网络开发の2】XML之SAX方式 解析和生成XML文件
- Android中使用SAX方式解析XML文件
- JAVA SAX 方式解析XML文件
- android学习——使用SAX、DOM 和 PULL 解析xml文件,及使用pull生成xml文件
- Android 解析XML文件的三种方式 DOM,SAX,PULL
- WCF生成客户端对象方式解析
- Android中使用SAX方式解析XML文件
- PULL解析方式生成XML文件
- 解析XML文件(SAX方式解析XML)
- java解析xml文件的2种方法:sax,dom
- java语言连接mysql数据库并利用XML解析工具DOM生成XML文件,然后利用DOM SAX对所生成XML文件里的详细信息进行解析
- WCF生成客户端对象方式解析
- SAX方式解析XML的简单方法
- WCF生成客户端对象方式解析
- Android学习札记10:用SAX解析XML文件时,当标签中出现换行符时可能出现读取内容为空的解决方法
- Android SAX方式解析XML文件
- SAX 解析XML文件(相对解析的所有方法来说,这种最简单)