您的位置:首页 > 其它

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]

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: