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

来源:互联网 发布:美国m2数据 编辑:程序博客网 时间:2024/05/19 13:23

/******************************************
* 程序编写: 陈林茂
* 编写日期: 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之中去.

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 幼儿园小孩数字记不住怎么办 大班教案走丢了怎么办 ppt加视频反了怎么办 拔罐之后背疼怎么办 拔完火罐后背疼怎么办 打印机红色的口堵了怎么办 打印机红色复印不出来怎么办 打印机加错颜色墨水怎么办 中班安全教案脚扭伤了怎么办 中班脚扭伤了怎么办教案 中班安全脚扭伤了怎么办 中班安全脚扭伤了怎么办反思 走丢了怎么办教案反思 汽车后轱辘不转怎么办 走丢了怎么办社会教案 小老鼠搬鸡蛋鸡蛋太大怎么办 小班走丢了怎么办教案 小班走丢了怎么办反思 房屋外墙漏水物业不管怎么办 厨房墙砖用色花怎么办 小孩子做错事很偏激怎么办 孩子在学校偷钱怎么办 房间墙壁上到处有湿虫怎么办 买了西晒的房子怎么办 墙面瓷砖下水管漏水怎么办 西晒房间开空调没效果怎么办 墙纸被小孩画了怎么办 集成墙板缝隙大怎么办 高血压变低血压怎么办会恢复吗 总是感觉睡不够好困怎么办 两岁宝宝说有鬼怎么办 阳台改成了卧室晒衣服怎么办 室外墙角边墙泥受潮脱落怎么办 新房装修墙体发霉了怎么办 宝宝吃多了发烧怎么办 宝宝睡觉不爱盖被子怎么办 1岁宝宝不盖被子怎么办 2岁宝宝不盖被子怎么办 买的芬琳漆不够刷的怎么办 1.3米宽厨房门怎么办 墙面漆颜色刷深了怎么办