package com.ejintai.epcis_agro.transmission.fileDeal.impl;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import com.ejintai.epcis_agro.anno.ExcelAnno;
import com.ejintai.epcis_agro.biz.validation.Validation;
import com.ejintai.epcis_agro.biz.validation.ValidationFactory;
import com.ejintai.epcis_agro.constant.AlertCause;
/**
* 创建SAX解析处理器必须继承自
* org.xml.sax.helpers.DefaultHandler
* 实现响应的方法。
*/
public class ExcelSheetSAXHandler extends DefaultHandler {
@Autowired
protected @Value("${excelImport.maxRow}")
int maxRow;
private SharedStringsTable sst;
private String lastContents;
private boolean nextIsString;
public List<Object> result = new ArrayList<Object>();
private Class<?> excelVOs;
private String edrReason;
private Map<Integer, String> autoRead;
private Map<String, Validation> validationMap;
private int sheetIndex;
private Object vo;
private int r=1;//行
private int c=0;//例
int rowNum = 1;
int td;
private boolean nextIsRows; //是否新的一行
public ExcelSheetSAXHandler(SharedStringsTable sst,Class<?> excelVOs,String edrReason,int sheetIndex) {
this.sst = sst;
this.excelVOs=excelVOs;
this.edrReason=edrReason;
this.sheetIndex=sheetIndex;
autoRead = getMappingFromClass(excelVOs);
validationMap = getValidationMappingFromClass(excelVOs);
try{
vo = excelVOs.newInstance();
}catch (Exception e) {
// TODO: handle exception
}
}
public void startElement(String uri, String localName, String name,
Attributes attributes) throws SAXException{
// c => cell
if(name.equals("c")) {
// System.out.print("单元格"+attributes.getValue("r") + " - ");
if(c<26){//26个字母
td=Integer.parseInt(attributes.getValue("r").substring(1)); //这里还是有缺陷。当例数超过Z,就不能这样处理了。
}else if(c<702){//到ZZ那里
td=Integer.parseInt(attributes.getValue("r").substring(2));
}else{
//太多例,不支持
throw new SAXException("太多例,不支持" );
}
if(td==r){//表示它们是一行的数据
c++;//计算例
r=td;
nextIsRows=false;
}else{
rowNum++;
c=0;
nextIsRows=true;
r=td;
}
String cellType = attributes.getValue("t");
if(cellType != null && cellType.equals("s")) {
nextIsString = true;
} else {
nextIsString = false;
}
}
// Clear contents cache
lastContents = "";
}
public void endElement(String uri, String localName, String name)
throws SAXException {
// Process the last contents as required.
// Do now, as characters() may be called more than once
if(nextIsString) {
int idx = Integer.parseInt(lastContents);
lastContents = new XSSFRichTextString(sst.getEntryAt(idx)).toString();
nextIsString = false;
}
// v => contents of a cell
// Output after we've seen the string contents
if(name.equals("v")) {
// System.out.println("数据"+lastContents);
if(r!=1){//行 第一行不处理
if(nextIsRows){//新的一行
if(r>2){
result.add(vo);
}
try{
vo = excelVOs.newInstance();
}catch (Exception e) {
// TODO: handle exception
}
setVo();
}else{
setVo();
}
}
}
}
/**
* 设置每行数据
*/
private void setVo() throws SAXException{
String propName = autoRead.get(c);
if (null != propName) {//例
try{
BeanUtils.setProperty(vo, propName, lastContents);
}catch (Exception e) {
// TODO: handle exception
}
}
}
public void characters(char[] ch, int start, int length)
throws SAXException {
lastContents += new String(ch, start, length);
}
/**
* 接收文档结束的通知
*/
public void endDocument(){
result.add(vo);
// System.out.println("接收文档结束");
}
public void startDocument(){
//System.out.println("接收文档开始");
}
private Map<Integer, String> getMappingFromClass(Class<?> annoClass) {
Map<Integer, String> mapping = new HashMap<Integer, String>();
// 枚举每一列和字段的对应关系
Field[] fields = annoClass.getDeclaredFields();
for (Field field : fields) {
boolean hasAnnotation = field.isAnnotationPresent(ExcelAnno.class);
// 有注解的才从Excel读取
if (hasAnnotation) {
ExcelAnno anno = field.getAnnotation(ExcelAnno.class);
int column = anno.column();
String fieldName = field.getName();
mapping.put(column, fieldName);
}
}
return mapping;
}
private Map<String, Validation> getValidationMappingFromClass(
Class<?> annoClass) {
Map<String, Validation> mapping = new HashMap<String, Validation>();
// 枚举每一列和字段的对应关系
Field[] fields = annoClass.getDeclaredFields();
for (Field field : fields) {
boolean hasAnnotation = field.isAnnotationPresent(ExcelAnno.class);
// 有注解的才从Excel读取
if (hasAnnotation) {
ExcelAnno anno = field.getAnnotation(ExcelAnno.class);
Class valiClass = anno.validationClass();
Validation validation = ValidationFactory
.getValidation(valiClass);
String fieldName = field.getName();
mapping.put(fieldName, validation);
}
}
return mapping;
}
public List<Object> getResult() {
return result;
}
public void setResult(List<Object> result) {
this.result = result;
}
public Class<?> getExcelVOs() {
return excelVOs;
}
public void setExcelVOs(Class<?> excelVOs) {
this.excelVOs = excelVOs;
}
public String getEdrReason() {
return edrReason;
}
public void setEdrReason(String edrReason) {
this.edrReason = edrReason;
}
}
分享到:
相关推荐
2. **设置事件处理器**:通过`SAXParser`的`setHandler`方法设置一个实现了`ContentHandler`接口的对象,这个对象将处理SAX解析过程中触发的事件。 3. **解析XML**:调用`parse`方法,传入XML文件的输入流或URL,...
// 使用工厂创建SAX解析器 SAXParser saxParser = factory.newSAXParser(); // 创建自定义的事件处理器 SaxDemoHandler handler = new SaxDemoHandler(); // 加载XML文件并开始解析 File inputFile = new ...
在主函数中,我们设置解析工厂,创建SAX解析器,并使用它来解析`person.xml`文件。 SAX解析器的另一个重要概念是实体解析器(EntityResolver),它可以处理XML文档中的外部实体引用。如果XML文件包含外部DTD(文档...
4. **创建SAX解析器**:使用`SAXParserFactory`的`newInstance()`方法创建一个解析器工厂,然后调用`newSAXParser()`方法生成SAX解析器实例。 5. **实现ContentHandler**:创建一个实现了`org.xml.sax....
5. **创建SAX解析器处理类** - 在`DefaultHandler`子类中,`startElement()`方法会在遇到元素开始标签时调用,可以记录当前元素的名称。 - `endElement()`方法在元素结束时调用,可用于结束当前元素的处理。 - `...
相比之下,SAX解析器采用事件驱动模型,逐行读取XML文档,遇到元素、属性等结构时触发相应的事件。这种方法不将整个文档加载到内存,因此更适用于处理大型或内存受限的环境。然而,由于SAX是基于事件的,它不提供...
在使用SAX解析XML前,需要创建一个解析器实例。Java中,可以使用`SAXParserFactory`来生成`SAXParser`,然后调用`parse()`方法解析XML文件。例如: ```java SAXParserFactory factory = SAXParserFactory.new...
SAX解析器以流式方式处理XML,当遇到文档的不同部分(如开始标签、结束标签、文本节点等)时,会触发相应的事件处理器。我们可以利用这些事件来构建JSON对象。 描述中指出,示例代码中的类可以稍作修改以实现通用性...
接下来,我们将深入探讨天气预报接口、SAX解析以及如何处理XML数据。 首先,天气预报接口是一个API(Application Programming Interface),它提供了获取当前或未来天气信息的途径。这些接口通常由气象服务机构提供...
SAX解析器逐行读取XML文件,只在需要时处理数据,显著降低了内存需求。 SAX解析的核心在于事件驱动模型。当解析器读取XML文件时,遇到开始元素、结束元素、字符数据等,它会触发相应的事件,并调用预先注册的处理器...
1. **初始化解析器**:程序首先创建一个SAX解析器实例,并注册事件处理器(ContentHandler)。 2. **设置事件处理器**:事件处理器包含一系列回调方法,如`startElement()`、`endElement()`、`characters()`等,当...
SAX解析的基本原理是读取XML文档,当遇到文档的开始、结束、元素、属性等结构时,会触发相应的事件处理器方法。程序员通过实现SAX解析器的回调接口,为这些事件编写处理代码,从而解析XML数据。以下是一些关键的SAX...
1. 创建SAX解析器工厂:`SAXParserFactory factory = SAXParserFactory.newInstance();` 2. 配置和获取解析器:`SAXParser parser = factory.newSAXParser();` 3. 创建自定义的事件处理器:`class MyHandler extends...
2. 创建SAX解析器:使用`SAXParserFactory`创建`SAXParser`实例。这一步会初始化解析器,并设置解析行为。 ```java SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); SAXParser saxParser =...
2. 创建事件处理器:SAX解析需要一个事件处理器,它会在解析过程中触发特定事件,例如开始读取工作表、读取单元格等。你需要创建一个实现`XSSFSheetXMLHandler.SheetContentsHandler`接口的类,覆盖其方法来处理这些...
首先,我们需要了解SAX解析的基本步骤: 1. **创建解析器**:使用`SAXParserFactory`来创建`SAXParser`实例。这个工厂类是JAXB的一部分,允许我们配置解析器的行为。 ```java SAXParserFactory factory = ...
SAX解析是一种流式的XML解析方式,它使用了一种基于事件的模型来处理XML文档。开发者不需要在内存中构建整个文档的树形结构,而是通过响应XML解析器发出的事件来处理XML文档。这种方式特别适合处理大型的XML文件,...
SAX解析器的工作原理是逐行读取XML文档,当遇到特定的XML元素时,如开始标签、结束标签、属性等,会触发相应的事件处理器方法。这种方法与DOM(Document Object Model)解析不同,DOM一次性加载整个XML文档到内存,...
SAX(Simple API for XML)是一种轻量级的XML解析方式,它以事件驱动的方式处理XML文档。在SAX解析中,XML文档被...通过理解SAX解析的工作原理和编写适当的事件处理器,开发者可以有效地从XML文件中提取所需的信息。
5. 最后,创建SAX解析器实例,设置我们的处理器,并调用`parse`方法开始解析XML。 ```java public class MyHandler extends DefaultHandler { @Override public void startElement(String uri, String localName,...