使用STAX Parser将XML解组到不同对象的三个列表 [英] Unmarshalling XML to three lists of different objects using STAX Parser
问题描述
有没有一种方法可以使用STAX解析器有效地解析具有不同类的对象的多个列表(POJO)的XML文档. 我的XML的确切结构如下(类名不是真实的)
Is there a way I can use STAX parser to efficiently parse an XML document with multiple lists of objects of different classes (POJO). The exact structure of my XML is as follows (class names are not real)
<?xml version="1.0" encoding="utf-8"?>
<root>
<notes />
<category_alpha>
<list_a>
<class_a_object></class_a_object>
<class_a_object></class_a_object>
<class_a_object></class_a_object>
<class_a_object></class_a_object>
.
.
.
</list_a>
<list_b>
<class_b_object></class_b_object>
<class_b_object></class_b_object>
<class_b_object></class_b_object>
<class_b_object></class_b_object>
.
.
.
</list_b>
</category_alpha>
<category_beta>
<class_c_object></class_c_object>
<class_c_object></class_c_object>
<class_c_object></class_c_object>
<class_c_object></class_c_object>
<class_c_object></class_c_object>
.
.
.
.
.
</category_beta>
</root>
我一直在使用STAX Parser,即XStream库,链接: XStream
I have been using the STAX Parser i.e. XStream library, link: XStream
只要我的XML包含一类对象的列表,它绝对可以正常工作,但是我不知道如何处理包含不同类的对象列表的XML.
It works absolutely fine as long as my XML contains list of one class of objects but I dont know how to handle an XML that contains list of objects of different classes.
任何帮助将不胜感激,如果我没有提供足够的信息或者我没有正确说明问题,请告诉我.
Any help would be really appreciated and please let me know if I have not provided enough information or I haven't phrased the question properly.
推荐答案
您可以使用声明性流映射(DSM)流解析库,可以轻松地将复杂的XML转换为java类.它使用StAX解析XML.
You can use Declarative Stream Mapping (DSM) stream parsing library to easily convert complex XML to java class. It uses StAX to parse XML.
我跳过获取 notes 标记的操作,并在 class_x_object 标记中添加了一个字段以进行演示.
I skip getting notes tag and add a field inside class_x_object tags for demostration.
这是XML:
<?xml version="1.0" encoding="utf-8"?>
<root>
<notes />
<category_alpha>
<list_a>
<class_a_object>
<fieldA>A1</fieldA>
</class_a_object>
<class_a_object>
<fieldA>A2</fieldA>
</class_a_object>
<class_a_object>
<fieldA>A3</fieldA>
</class_a_object>
</list_a>
<list_b>
<class_b_object>
<fieldB>B1</fieldB>
</class_b_object>
<class_b_object>
<fieldB>B2</fieldB>
</class_b_object>
<class_b_object>
<fieldB>B3</fieldB>
</class_b_object>
</list_b>
</category_alpha>
<category_beta>
<class_c_object>
<fieldC>C1</fieldC>
</class_c_object>
<class_c_object>
<fieldC>C2</fieldC>
</class_c_object>
<class_c_object>
<fieldC>C3</fieldC>
</class_c_object>
</category_beta>
</root>
首先,您必须以yaml或JSON格式定义XML数据和您的类字段之间的映射.
First of all, you must define the mapping between XML data and your class fields in yaml or JSON format.
以下是映射定义:
result:
type: object
path: /root
fields:
listOfA:
type: array
path: .*class_a_object # path is regex
fields:
fieldOfA:
path: fieldA
listOfB:
type: array
path: .*class_b_object
fields:
fieldOfB:
path: fieldB
listOfC:
type: array
path: .*class_c_object
fields:
fieldOfC:
path: fieldC
您要反序列化的Java类:
Java class that you want to deserialize:
public class Root {
public List<A> listOfA;
public List<B> listOfB;
public List<C> listOfC;
public static class A{
public String fieldOfA;
}
public static class B{
public String fieldOfB;
}
public static class C{
public String fieldOfC;
}
}
用于解析XML的Java代码:
Java Code to parse XML:
DSM dsm=new DSMBuilder(new File("path/to/mapping.yaml")).setType(DSMBuilder.TYPE.XML).create(Root.class);
Root root = (Root)dsm.toObject(xmlFileContent);
// write root object as json
dsm.getObjectMapper().writerWithDefaultPrettyPrinter().writeValue(System.out, object);
此处输出:
{
"listOfA" : [ {"fieldOfA" : "A1"}, {"fieldOfA" : "A2"}, {"fieldOfA" : "A3"} ],
"listOfB" : [ {"fieldOfB" : "B1"}, {"fieldOfB" : "B2"}, "fieldOfB" : "B3"} ],
"listOfC" : [ {"fieldOfC" : "C1"}, {"fieldOfC" : "C2"}, {"fieldOfC" : "C3"} ]
}
更新:
据您的评论我了解到,您希望将大型XML文件作为流读取.在读取文件时处理数据.
As I understand from your comment, you want to read big XML file as a stream. and process data while you are reading the file.
DSM允许您在读取XML时处理数据.
DSM allows you to do process data while you are reading XML.
声明三种不同的功能来处理部分数据.
Declare three different functions to process partial data.
FunctionExecutor processA=new FunctionExecutor(){
@Override
public void execute(Params params) {
Root.A object=params.getCurrentNode().toObject(Root.A.class);
// process aClass; save to db. call service etc.
}
};
FunctionExecutor processB=new FunctionExecutor(){
@Override
public void execute(Params params) {
Root.B object=params.getCurrentNode().toObject(Root.B.class);
// process aClass; save to db. call service etc.
}
};
FunctionExecutor processC=new FunctionExecutor(){
@Override
public void execute(Params params) {
Root.C object=params.getCurrentNode().toObject(Root.C.class);
// process aClass; save to db. call service etc.
}
};
向DSM注册功能
DSMBuilder builder = new DSMBuilder(new File("path/to/mapping.yaml")).setType(DSMBuilder.TYPE.XML);
// register function
builder.registerFunction("processA",processA);
builder.registerFunction("processB",processB);
builder.registerFunction("processC",processC);
DSM dsm= builder.create();
Object object = dsm.toObject(xmlContent);
更改映射文件以调用注册功能
change Mapping file to call registered function
result:
type: object
path: /root
fields:
listOfA:
type: object
function: processA # when 'class_a_object' tag closed processA function will be executed.
path: .*class_a_object # path is regex
fields:
fieldOfA:
path: fieldA
listOfB:
type: object
path: .*class_b_object
function: processB# register function
fields:
fieldOfB:
path: fieldB
listOfC:
type: object
path: .*class_c_object
function: processC# register function
fields:
fieldOfC:
path: fieldC
这篇关于使用STAX Parser将XML解组到不同对象的三个列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!