最近需要解析大型的xml文件,找到的工具只有dom形式的,会占用大量的内存,所以基于java自带的sat工具封装了一个流式解析器,支持逐条处理、入库。支持以注解的形式将xml中的元素与java类和字段对应上如:
一、依赖
<dependency>
<groupId>io.github.bithesenior</groupId>
<artifactId>huge-xml-resolver</artifactId>
<version>1.1-release</version>
</dependency>
二、注解
1、@FieldXMLElement
用于字段上,被标记的字段会被扫描,当name与xml的元素相同时,会调用setMethod而被映射;name默认与字段名相同,setMethod默认为字段对应的set方法驼峰命名。
例如:
2、@ObjectXMLElement
用于类上,被标记的类会被扫描,当name与xml的元素相同时,会创建一个该类的对象;
例如:
这里类名和部分字段使用了上文提到的默认值,当xml中出现<book>节点开始时,创建一个book对象,当</book>节点结束时调用上一级的addBook方法存入list,如果此节点为根节点则存入resultList,如果指定了rootmethod,那么该对象不会被存储,而是单独处理,比如逐条入库则需要这个用法;
三、方法
SATxmlUtils共提供了三个方法,分别是读xml文件,读zip文件,读文件流,用法相似,只是入参不同。
四、实例
xml格式如下
<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
<holder name ="xiaoming">xxxxxxxxxmmmmmmmmm</holder>
<book id="1">
<name>冰与火之歌</name>
<author>乔治马丁</author>
<year>2014</year>
<sth>abcdef</sth>
<language i:nil="true" />
<price>89</price>
</book>
<book id="2">
<name>安徒生童话</name>
<year>2004</year>
<price>77</price>
<language>English</language>
<page>
<value>1</value>
<context>abc</context>
</page>
<page>
<value>2</value>
<context>def</context>
</page>
</book>
</bookstore>
各java entity类如下
package dto;
import anos.ObjectXMLElement;
import java.util.ArrayList;
import java.util.List;
@ObjectXMLElement(name ="bookstore")
public class Bookbookstore {
Holder holder;
public Holder getHolder() {
return holder;
}
public void setHolder(Holder holder) {
this.holder = holder;
}
List<Book> books = new ArrayList<Book>();
public List<Book> getBooks() {
return books;
}
public void setBooks(List<Book> books) {
this.books = books;
}
public void addBook(Book book) {
books.add(book);
}
}
package dto;
import anos.FieldXMLElement;
import anos.ObjectXMLElement;
import java.util.ArrayList;
import java.util.List;
@ObjectXMLElement(addMethod = "addBook")
public class Book {
@FieldXMLElement
String id;
@FieldXMLElement
String name;
@FieldXMLElement
String author;
@FieldXMLElement(setMethod = "setYearrrrrrr")
String year;
@FieldXMLElement(name = "price")
String bookPrice;
Language language;
List<Page> pages = new ArrayList<Page>();
public void resolveBysingle(){
System.out.println("addToDatabase"+this.id);
}
public void addPage(Page page) {
pages.add(page);
}
public Language getLanguage() {
return language;
}
public void setLanguage(Language language) {
this.language = language;
}
public List<Page> getPages() {
return pages;
}
public void setPages(List<Page> pages) {
this.pages = pages;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getYear() {
return year;
}
public void setYearrrrrrr(String year) {
this.year = year;
}
public String getBookPrice() {
return bookPrice;
}
public void setBookPrice(String bookPrice) {
this.bookPrice = bookPrice;
}
}
package dto;
import anos.FieldXMLElement;
import anos.ObjectXMLElement;
@ObjectXMLElement(addMethod = "setHolder")
public class Holder {
@FieldXMLElement(name = "name",setMethod = "setName")
String name;
@FieldXMLElement(name = "holder",setMethod = "setComment")
String comment ;
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package dto;
import anos.FieldXMLElement;
import anos.ObjectXMLElement;
/**
* @author: oooooooooldbi
* @date: 2025/4/17 10:05
* @email: bithesenior@163.com
*/
@ObjectXMLElement(name="language",addMethod = "setLanguage")
public class Language {
@FieldXMLElement(name = "language",setMethod = "setLanguage")
String language;
@FieldXMLElement(name = "i:nil",setMethod = "setiNill")
String iNill;
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
public String getiNill() {
return iNill;
}
public void setiNill(String iNill) {
this.iNill = iNill;
}
}
package dto;
import anos.FieldXMLElement;
import anos.ObjectXMLElement;
@ObjectXMLElement(name ="page",addMethod = "addPage")
public class Page {
@FieldXMLElement(name = "value",setMethod = "setValue")
String value;
@FieldXMLElement(name = "context",setMethod = "setContext")
String context;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getContext() {
return context;
}
public void setContext(String context) {
this.context = context;
}
}
运行结果如下,book对象被加入了resultList之中
接下来修改Book类的注解,使其实现逐条处理的功能
package dto;
import anos.FieldXMLElement;
import anos.ObjectXMLElement;
import java.util.ArrayList;
import java.util.List;
@ObjectXMLElement(addMethod = "addBook",rootMethod = "resolveBysingle")
public class Book {
@FieldXMLElement
String id;
@FieldXMLElement
String name;
@FieldXMLElement
String author;
@FieldXMLElement(setMethod = "setYearrrrrrr")
String year;
@FieldXMLElement(name = "price")
String bookPrice;
Language language;
List<Page> pages = new ArrayList<Page>();
public void resolveBysingle(){
System.out.println("addToDatabase"+this.id);
}
public void addPage(Page page) {
pages.add(page);
}
public Language getLanguage() {
return language;
}
public void setLanguage(Language language) {
this.language = language;
}
public List<Page> getPages() {
return pages;
}
public void setPages(List<Page> pages) {
this.pages = pages;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getYear() {
return year;
}
public void setYearrrrrrr(String year) {
this.year = year;
}
public String getBookPrice() {
return bookPrice;
}
public void setBookPrice(String bookPrice) {
this.bookPrice = bookPrice;
}
}
可以看到,这个单独处理的方法被执行了
而resultList里面没有了这些对象
值得注意的是由于本工具的原理是基于反射创建对象,故不能直接使用Spring 中的bean,即单独处理时不能使用形如以下格式的代码,需要特殊处理,后文会给出。也可以自行搜索“new 出来的对象使用 spring bean”
@Autowired
BookService service
public void resolveBysingle(){
service.xxx();
//System.out.println("addToDatabase"+this.id);
}