将XML解析为Java对象节点 [英] Parsing XML to Java Object Node

查看:103
本文介绍了将XML解析为Java对象节点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当前,当我尝试将xml文档解析为Java Object时遇到问题.我要保留的唯一必要信息是 iid 时间列表.

Currently I'am facing problem when trying to parse a xml document to a Java Object. The only necessary information which i want to keep is the iid and time list.

xml测试文件:

    <items>
       <item>
        <iid>14</iid>
          <options>
              <option>
                <times>
                  <time>
                   <timeentry>20200714100100</timeentry>                           
                   <timetill>20200714101500</timetill>
                   <timemaxcount>2</timemaxcount>
                  </time>
                  <time>
                   <timeentry>20200714101600</timeentry>
                   <timetill>20200714103000</timetill>
                   <timemaxcount>2</timemaxcount>
                  </time>
                 <time>
                  <timeentry>20200714103100</timeentry>
                  <timetill>20200714104500</timetill>
                  <timemaxcount>2</timemaxcount>
                 </time>
                 <time>
                  <timeentry>20200714104600</timeentry>
                  <timetill>20200714110000</timetill>
                  <timemaxcount>2</timemaxcount>
                  </time
              </option>
          </options>
         </item>
      </items>

我创建了两个Java对象类,其中包含iid和时间列表.解析xml文件时,仅填充字段iid且list对象为null.我想念什么?

I have created two Java Objects classes which contains the iid and the time list. When parsing the xml file only the field iid gets filled and the list object is null. What do I missing ?

@JsonIgnoreProperties(ignoreUnknown = true)
@XmlRootElement(name = "item")
@JacksonXmlRootElement(localName = "item")
public class SubProduct implements Serializable {

    private String iid;

    @JacksonXmlElementWrapper(localName = "times")
    @JacksonXmlProperty(localName = "time")
    private List<TimePeriod> times;
}

@JsonIgnoreProperties(ignoreUnknown = true)
@JacksonXmlRootElement(localName = "time")
public class TimePeriod implements Serializable {
    @JsonProperty(value = "timeentry")
    String timeEntry;
    @JsonProperty(value = "timetill")
    String timeTill;
    @JsonProperty(value = "timemaxcount")
    String timeMaxCount;
}

服务层:

...
NodeList itemList = document.getElementsByTagName("item"); 
List<SubProduct> subProducts = new ArrayList<>();
        for (int i = 0; i < nodes.getLength(); i++) {
            SubProduct value = xmlMapper.readValue(nodeToString(nodes.item(i)), SubProduct.class);
            subProducts.add(value);
            
        }
        return subProducts;

...

 public static String nodeToString(Node node) throws Exception{
        StringWriter sw = new StringWriter();

        Transformer t = TransformerFactory.newInstance().newTransformer();
        t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
        t.setOutputProperty(OutputKeys.INDENT, "yes");
        t.transform(new DOMSource(node), new StreamResult(sw));

        return sw.toString();
    }

回复:

   {
        "iid": "9",
        "times": null
    },

推荐答案

您不需要将JacksonJAXBTransformer类混合.您可以将给定的XML有效负载直接反序列化为POJO模型. itemsoptionstimes节点表示节点List.我们可以将映射到以下模型:

You do not need to mix Jackson with JAXB or Transformer class. You can directly deserialise given XML payload to POJO model. items, options and times nodes represent List of nodes. We can map the to below model:

@Data
@ToString
class Item {
    private int iid;
    private List<Option> options;
}

@Data
@ToString
class Option {

    private List<Time> times;
}

@Data
@ToString
class Time {

    @JsonFormat(pattern = "yyyyMMddHHmmss")
    @JsonProperty("timeentry")
    private LocalDateTime entry;

    @JsonFormat(pattern = "yyyyMMddHHmmss")
    @JsonProperty("timetill")
    private LocalDateTime till;

    @JsonProperty("timemaxcount")
    private int maxCount;
}

我使用了 Lombok 注释来避免样板代码.简单用法:

I used Lombok annotations to avoid boilerplate code. Simple usage:

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import lombok.Data;
import lombok.ToString;

import java.io.File;
import java.time.LocalDateTime;
import java.util.List;

public class XmlMapperApp {

    public static void main(String... args) throws Exception {
        File xmlFile = new File("./resource/test.xml").getAbsoluteFile();

        XmlMapper mapper = XmlMapper.xmlBuilder()
                .addModule(new JavaTimeModule())
                .build();
        List<Item> items = mapper.readValue(xmlFile, new TypeReference<List<Item>>() {
        });
        items.forEach(item -> {
            System.out.println("Id => " + item.getIid());
            System.out.println("Times => ");
            item.getOptions().stream().flatMap(o -> o.getTimes().stream())
                    .forEach(System.out::println);
        });
    }
}

上面的代码显示:

Id => 14
Times => 
Time(entry=2020-07-14T10:01, till=2020-07-14T10:15, maxCount=2)
Time(entry=2020-07-14T10:16, till=2020-07-14T10:30, maxCount=2)
Time(entry=2020-07-14T10:31, till=2020-07-14T10:45, maxCount=2)
Time(entry=2020-07-14T10:46, till=2020-07-14T11:00, maxCount=2)

另请参阅:

  • Java 8 flatMap example
  • jackson-modules-java8

这篇关于将XML解析为Java对象节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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