分享
 
 
 

如何方便地操纵XML中的数据(JAVA代码具体实现)

王朝java/jsp·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

/******************************************

* 程序编写: 陈林茂

* 编写日期: 2003-03-16

* 联系作者: linmaochen@sohu.com

*******************************************/

众所周知,XML在现在的WEB应用程序中已非常炙手,但在程序中,我们如何很好的控制

XML中的数据,同时如何组合您的XML数据,确是一个比较麻烦的问题,下面的例子中我

将将我的一些解决办法介绍给大家:

1。首先,请大家看清下面的两个XML文件:

STRUCT.XML 为数据信息的具体结构描述;

Employees.xml : 则为具体的XML数据信息.

下面为具体的XML文本内容:

struct.xml:

<?xml version="1.0"?>

<Fieldset>

<Field>

<FieldName>EmpNo</FieldName>

<FieldType>1</FieldType>

<FieldSize>4</FieldSize>

</Field>

<Field>

<FieldName>FirstName</FieldName>

<FieldType>1</FieldType>

<FieldSize>8</FieldSize>

</Field>

<Field>

<FieldName>LastName</FieldName>

<FieldType>1</FieldType>

<FieldSize>8</FieldSize>

</Field>

<Field>

<FieldName>PhoneExt</FieldName>

<FieldType>1</FieldType>

<FieldSize>20</FieldSize>

</Field>

<Field>

<FieldName>HireDate</FieldName>

<FieldType>3</FieldType>

<FieldSize>10</FieldSize>

</Field>

<Field>

<FieldName>DeptNo</FieldName>

<FieldType>1</FieldType>

<FieldSize>10</FieldSize>

</Field>

<Field>

<FieldName>JobCode</FieldName>

<FieldType>1</FieldType>

<FieldSize>10</FieldSize>

</Field>

<Field>

<FieldName>JobGrade</FieldName>

<FieldType>1</FieldType>

<FieldSize>10</FieldSize>

</Field>

<Field>

<FieldName>JobCountry</FieldName>

<FieldType>1</FieldType>

<FieldSize>20</FieldSize>

</Field>

<Field>

<FieldName>Salary</FieldName>

<FieldType>4</FieldType>

<FieldSize>20</FieldSize>

</Field>

<Field>

<FieldName>FullName</FieldName>

<FieldType>1</FieldType>

<FieldSize>30</FieldSize>

</Field>

</Fieldset>

-----------------------------------------------------------------------------------

Employees.xml

<?xml version="1.0"?>

<RecordSet>

<Record>

<EmpNo>2</EmpNo>

<FirstName>Robert</FirstName>

<LastName>Nelson</LastName>

<PhoneExt>250</PhoneExt>

<HireDate>1988-12-28</HireDate>

<DeptNo>600</DeptNo>

<JobCode>VP</JobCode>

<JobGrade>2</JobGrade>

<JobCountry>USA</JobCountry>

<Salary>105900.000000</Salary>

<FullName>Nelson, Robert</FullName>

</Record>

<Record>

<EmpNo>4</EmpNo>

<FirstName>Bruce</FirstName>

<LastName>Young</LastName>

<PhoneExt>233</PhoneExt>

<HireDate>1988-12-28</HireDate>

<DeptNo>621</DeptNo>

<JobCode>Eng</JobCode>

<JobGrade>2</JobGrade>

<JobCountry>USA</JobCountry>

<Salary>97500.000000</Salary>

<FullName>Young, Bruce</FullName>

</Record>

<Record>

<EmpNo>5</EmpNo>

<FirstName>Kim</FirstName>

<LastName>Lambert</LastName>

<PhoneExt>22</PhoneExt>

<HireDate>1989-02-06</HireDate>

<DeptNo>130</DeptNo>

<JobCode>Eng</JobCode>

<JobGrade>2</JobGrade>

<JobCountry>USA</JobCountry>

<Salary>102750.000000</Salary>

<FullName>Lambert, Kim</FullName>

</Record>

</RecordSet>

2.为了很好的并且很直观的操纵XML的数据,我们将模拟一个类似于DELPHI中的QUERY 一样的组件,由于篇幅,

这里只提供它的简单实现:

它将包括三个基本的JAVA 类:

XFIELD.JAVA 单个字段信息的描述类;

XFIELDS.JAVA 单条记录信息的描述类;

XQUERY.JAVA 类似于QUERY 一样的查询类的控件.下面为三个类具体实现的源代码:

/**

* <p>Title: 字段单元</p>

* <p>Description: 内存记录中字段信息描述</p>

* <p>Copyright: Copyright (c) 2002</p>

* <p>Company: </p>

* @author 陈林茂 2003-03-12

* @version 1.0

*/

import java.lang.*;

import java.lang.Double;

/*

* 描述内存记录中的字段信息

*/

/*******************************************************

* log:

* 2003-03-12 : add XField

********************************************************/

public class XField {

/*

* 字段类型说明:

* ftInteger : 整数字段

* ftString : 字符串字段

* ftDate : 日期型字段

* ftFloat : 浮点型字段信息

*/

private static int ftString = 1;

private static int ftInteger = 2;

private static int ftDate = 3;

private static int ftFloat = 4;

/**************************************/

private String FieldName;

private int FieldType;

private String FieldValue;

private int FieldSize = 0;

public XField() {

}

public XField(String fldName){

FieldName = fldName;

}

public XField(String fldName,int fldType){

FieldName = fldName;

FieldType = fldType;

}

public XField(String fldName,int fldType,String fldValue){

FieldName = fldName;

FieldType = fldType;

FieldValue = fldValue;

}

//获取字段的名称

public String getFieldName(){

return this.FieldName ;

}

//获取字段的类别

public int getFieldType(){

return FieldType;

}

//设置字段的类别

public void setFieldType(int sFieldType){

this.FieldType = sFieldType ;

}

//设置字段的长度信息

public void setFieldSize(int sSize){

this.FieldSize = sSize ;

}

//获取当前字段的整型值

public int getAsInteger(){

if(IsInteger(FieldValue))

return Integer.parseInt(FieldValue);

return 0;

}

//获取当前字段的字符串值

public String getAsString(){

return FieldValue;

}

//获取当前字段的浮点型值

public double getAsFloat(){

if(IsFloat(FieldValue)){

return Double.parseDouble(FieldValue);

}

return 0.0;

}

//设置字段的值

public void setFieldValue(String sFldValue){

this.FieldValue = sFldValue;

}

/*

* 判断一字段值是否为整数

*/

private boolean IsInteger(String numStr){

int i=0;

for(i = 1;i < numStr.length(); i++){

if((numStr.charAt(i) <='0') || (numStr.charAt(i) >= '9' )){

return false;

}

}

return true;

}

/*

* 判断一字段值是否为浮点数

*/

private boolean IsFloat(String numStr){

int i=0;

for(i = 1;i < numStr.length(); i++){

if (numStr.charAt(i) != '.'){

if((numStr.charAt(i) <='0') || (numStr.charAt(i) >= '9' )){

return false;

}

}

}

return true;

}

/*

* 判断一字段值是否为日期型

*/

private boolean IsDateTime(String dateStr){

//to do

return true;

}

}

/**

* <p>Title: 内存单个记录信息类</p>

* <p>Description: 内存记录单个记录信息描述</p>

* <p>Copyright: Copyright (c) 2002</p>

* <p>Company: </p>

* @author 陈林茂 2003-03-13

* @version 1.0

*/

import java.util.*;

import java.lang.*;

import excelsample.XField;

/*

* XFields 类是将一些字段信息组合在一起,

* 从而组合成一个单条记录信息

* 它提供如下的功能:

* 1: 查找某一个字段信息

* 2: 重新设置某个字段的值

*/

public class XFields {

//字段信息容器

private Vector vector = new Vector(100);

public XFields() {

}

//添加一字段信息

public void AddXField(XField sFld){

vector.add(sFld);

}

//移去一字段信息

public void RemoveXField(XField sFld){

if(vector.size()>0)

vector.remove(sFld);

}

//返回记录中字段的个数

public int getCount(){

return vector.size() ;

}

//根据名称获取某个字段信息

public XField getFieldByname(String sFldName){

int i;

int pos ;

XField xfield;

for(i=0; i<vector.size(); i++){

xfield = (XField)(vector.elementAt(i));

System.out.println("field name is :"+xfield.getFieldName());

pos =xfield.getFieldName().toUpperCase().indexOf(sFldName.toUpperCase());

if(pos >= 0)

{

return xfield;

}

}

return null;

}

//根据序号获取某个字段信息

public XField getField(int Index){

if(vector.size() > Index)

return (XField)(vector.elementAt(Index));

return null;

}

//复制某一个字段信息

public XField CopyField(int index){

XField sfield;

if(this.vector.size() > index){

sfield =(XField)(vector.elementAt(index));

XField xfield =new XField(sfield.getFieldName(),

sfield.getFieldType(),

sfield.getAsString());

return xfield;

}

return null;

}

}

/**

* <p>Title: 内存记录集</p>

* <p>Description: 将XML文件中提供的记录信息存放到内存中</p>

* <p>Copyright: Copyright (c) 2002</p>

* <p>Company: </p>

* @author 陈林茂 2003-03-15

* @version 1.0

*/

/*

* 类的名称:XQuery

* 说明: 此类将模拟一个类似DELPHI QUERY 的结构信息;

* 1。 它提供记录的查找,移到第一条记录,移到下一条记录等操作;

* 2。 它同时包含结构及数据信息

* 3。 利用它可以方便地对内存中的数据进行检索

*/

import java.lang.*;

import java.util.*;

public class XQuery {

//内存记录容器

private Vector vector = new Vector(100);

//内存记录的结构信息

private XFields Struct = null;

//是否到记录的结尾

private boolean RecEof = true;

//当前操作的记录

private XFields CurrXFields = null;

//当前的记录编号

private int RecNo = 0;

public XQuery() {

}

//设置内存记录的结构信息

public void setSturcture(XFields sStruct){

this.Struct = sStruct;

}

//添加一记录信息

public void AddRecord(XFields xfields){

vector.add(xfields);

}

//移走一记录信息

public void RemoveRecord(XFields xfields){

if(vector.size() > 0 )

vector.remove(xfields);

}

//获取当前记录集的记录总数

public int getRecordCount(){

return vector.size();

}

/*

* 记录集的相关操作函数

*/

//移到第一条记录

public void First(){

if(vector.size()<=0){

this.RecEof = true;

return ;

}

CurrXFields = (XFields)(vector.elementAt(0));

this.RecEof = false;

this.RecNo = 0;

}

//移到下一条记录

public void Next(){

if(vector.size() == (this.RecNo+1)){

this.RecEof = true;

this.CurrXFields = null;

return ;

}

this.RecNo = this.RecNo + 1;

this.CurrXFields = (XFields)(vector.elementAt(this.RecNo));

this.RecEof =false;

}

//新增一空白记录信息

public void insertRecord(){

int i=0;

XFields xfields = new XFields();

for(i=0;i<this.Struct.getCount();i++){

xfields.AddXField(this.Struct.CopyField(i));

}

this.vector.add(xfields);

this.RecNo = this.vector.size();

this.CurrXFields = xfields;

System.out.println("insert a record!");

}

//获取记录集中的字段个数

public int getFieldsCount(){

return this.Struct.getCount() ;

}

//返回记录集的当前记录

public XFields RecordSet(){

return this.CurrXFields ;

}

//判断记录集是否到结尾

public boolean Eof(){

return this.RecEof ;

}

}

3.最后,就是告诉大家如何如何将XML中的数据读取出来,并放到XQUERY类中去,请看具体的实现:

(1) 建立一个解析XML文件的类(详见JBUILDER 中自带的示例):

import java.io.IOException;

import org.xml.sax.*;

import org.xml.sax.helpers.*;

import org.apache.xerces.parsers.SAXParser;

public class xmlParser extends DefaultHandler{

private static int INDENT = 4;

private static String attList = "";

//记录表信息

public static XQuery query =new XQuery();

//记录的结构信息

public XFields xfields=new XFields();

//临时的字段信息

private XField xfield = null;

private String elementName = "";

/*解析行为:

* 0: 解析XML文件中的信息为记录表的结构定义信息

* 1: 解析XML文件中的信息为记录表的具体的记录信息

*/

private static int parseMode =0;

private int idx = 0;

public void characters(char[] ch, int start, int length) throws SAXException {

String s = new String(ch, start, length);

if (ch[0] == '\n')

return;

System.out.println(getIndent() + " Value: " + s);

if(this.parseMode == 0){

if(this.elementName.indexOf("FieldName") >= 0) {

this.xfield = new XField(s);

System.out.println("Fieldname is :"+this.xfield.getFieldName());

}

if(this.elementName.indexOf("FieldType") >= 0){

if(this.xfield != null) {

try{

this.xfield.setFieldType(Integer.parseInt(s));

System.out.println("Fieldtype is:"+this.xfield.getFieldType());

}catch(Exception e){

e.printStackTrace();

}

}

}

if(this.elementName.indexOf("FieldSize") >= 0) {

if(this.xfield != null){

this.xfield.setFieldSize(Integer.parseInt(s)) ;

//添加一字段定义

this.xfields.AddXField(this.xfield);

System.out.println("record fields count is :" +this.xfields.getCount());

}

}

}

//

if(this.parseMode == 1) {

this.query.RecordSet().getFieldByname(this.elementName).setFieldValue(s);

}

}

public void endDocument() throws SAXException {

idx -= INDENT;

System.out.println(getIndent() + "end document");

System.out.println("...PARSING ends");

if(this.parseMode ==0)

this.query.setSturcture(this.xfields);

}

public void endElement(String uri, String localName, String qName) throws SAXException {

if (!attList.equals(""))

System.out.println(getIndent() + " Attributes: " + attList);

attList = "";

System.out.println(getIndent() + "end document");

idx -= INDENT;

System.out.println("the idx is :"+String.valueOf(idx));

}

public void startDocument() throws SAXException {

idx = 0;

idx += INDENT;

System.out.println("PARSING begins...");

System.out.println(getIndent() + "start document: ");

}

public void startElement(String uri, String localName, String qName,

Attributes attributes) throws SAXException {

idx += INDENT;

System.out.println('\n' + getIndent() + "start element: " + localName);

if (attributes.getLength() > 0) {

idx += INDENT;

for (int i = 0; i < attributes.getLength(); i++) {

attList = attList + attributes.getLocalName(i) + " = " + attributes.getValue(i);

if (i < (attributes.getLength() - 1))

attList = attList + ", ";

}

idx-= INDENT;

}

//判断是否为具体信息层

switch(this.parseMode){

case 0:

this.elementName = localName;

break;

case 1:

this.elementName = localName ;

if(this.elementName.indexOf("Record") >= 0)

if(idx == 12){

this.query.insertRecord();

}

break;

}

}

private String getIndent() {

StringBuffer sb = new StringBuffer();

for (int i = 0; i < idx; i++)

sb.append(" ");

return sb.toString();

}

public static void setQuery(XQuery sxquery){

query = sxquery;

}

//设置识别模式

public static void setMode(int sMode){

parseMode = sMode;

}

}

(2) 如何从XML中读取数据出来,并放到XQUERY去,并且自由的操作数据:

/**

* <p>Title: Excel 文件信息写入类</p>

* <p>Description: 从一个XML文件中读取信息并写入到EXCEL文件中去</p>

* <p>Copyright: Copyright (c) 2002</p>

* <p>Company: </p>

* @author 陈林茂 2003-03-15

* @version 1.0

*/

/*

* EXCEL记录写入演示

* 说明: 它主要分三个步骤:

* 1 读取STRUCT.XML文件,建立记录的字段结构信息;

* 2 读取RECORD.XML文件,获取具体的记录信息;

* 3 根据记录信息,将信息写入EXCEL文件

*/

import java.io.File;

import java.util.Date;

import jxl.*; //为EXCEL开源支持类库

import jxl.write.*;

import java.io.IOException;

import org.xml.sax.*;

import org.xml.sax.helpers.*;

import org.apache.xerces.parsers.SAXParser;

public class ExcelWrite {

public ExcelWrite() {

}

public static void main(String argv[]){

if(argv.length != 3){

System.out.println("The Application argument is "

+"java ExcelWrite [struct.xml] [record.xml] [output.xls]");

System.exit(-1);

}

String StructFile = argv[0];

String RecordFile = argv[1];

String outputFile = argv[2];

int i = 0;

int m = 0;

XQuery sQuery =new XQuery();

//建立内存记录信息

try {

//建立XML解析器

XMLReader parser = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");

xmlParser MySaxParserInstance = new xmlParser();

xmlParser.setQuery(sQuery);

parser.setContentHandler(MySaxParserInstance);

//解析记录集的结构信息

xmlParser.setMode(0);

parser.parse(StructFile);

System.out.println("the recordset fields count is :"+sQuery.getFieldsCount());

//解析记录集的数据信息

xmlParser.setMode(1);

parser.parse(RecordFile);

System.out.println("the recordset record count is :"+sQuery.getRecordCount());

}

catch(IOException ioe) {

ioe.printStackTrace();

}

catch(SAXException saxe) {

saxe.printStackTrace();

}

//开始写入数据信息

try{

//建立一EXCEL文件写入类

WritableWorkbook workbook = Workbook.createWorkbook(new File(outputFile));

//建立一工作薄

WritableSheet sheet = workbook.createSheet("员工记录数据", 0);

//建立每列的标题信息,具体操纵XQUERY中的数据

String s = "";

for(i = 0; i<sQuery.getFieldsCount(); i++){

s = sQuery.RecordSet().getField(i).getFieldName();

Label label = new Label(i, 0, s);

sheet.addCell(label);

}

//依次填入记录信息

m = 1 ;

sQuery.First();

while (sQuery.Eof()==false){

for(i=0; i<sQuery.getFieldsCount(); i++){

s = sQuery.RecordSet().getField(i).getAsString();

Label label = new Label(i, m, s);

sheet.addCell(label);

}

sQuery.Next();

m = m + 1;

}

//write the data to File

workbook.write();

workbook.close();

}catch(Exception e){

e.printStackTrace();

}

}

}

4.总结:

首先建立记录的原始记录信息,分成两个XML文件,其中一个为数据具体的结构描述,

另外一个为具体的数据信息;

然后建立一个类似QUERY的类,可以方便地控制内存中的数据信息(包括记录的上移 下移等);

接下来,建立一XML的解析器,首先解析结构信息,并初始化具体的XQUERY类;

然后解析数据信息,将数据信息填充到XQUERY之中去.

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有