使用STAX Parser将XML解组到不同对象的三个列表 [英] Unmarshalling XML to three lists of different objects using STAX Parser

查看:62
本文介绍了使用STAX Parser将XML解组到不同对象的三个列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有一种方法可以使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆