【问题标题】:How can I ingnore some elements when reading XML using Jackson/FasterXML?使用 Jackson/FasterXML 读取 XML 时如何忽略某些元素?
【发布时间】:2020-01-28 22:53:36
【问题描述】:

我想跳过除 first_name 、node100 及其子节点之外的所有节点。 我有这个 XML(实际上我有很多员工,每个员工标签都有很多节点):

 <employees>
        <employee>
            <first_name>John</first_name>
            <last_name>Doe</last_name>
            <age>26</age>
        </employee>
        <employee>
            <first_name>Peter</first_name>
            <last_name>Parker</last_name>
            <age>30</age>
        </employee>
    </employees>

我能够阅读使用 Jackson FasterXML。我创建了 2 个 POJOS 来映射上面的 XML 结构

  @JacksonXmlRootElement(localName = "employees") public final class Employees {
        @JacksonXmlElementWrapper(localName = "employee", useWrapping = false)
        private Employee[] employee;
//ommiteed getter and setters

public final class Employee {
    @JacksonXmlProperty(localName = "id", isAttribute = true)
    private String id;
    @JacksonXmlProperty(localName = "first_name")
    private String firstName;
    @JacksonXmlProperty(localName = "last_name")
    private String lastName;
    @JacksonXmlProperty(localName = "age")
    private int age;

现在在生产中,xml 在节点内有 1000 个节点

<employee>
                <first_name>John</first_name>
                <last_name>Doe</last_name>
                <age>26</age>
                <node1>  </node1>
                <node2>  </node2>

                ..

                <node100> 
                   <values> 
                  <value> val1 </value>
                  <value> val1 </value>
                  <value> val1 </value>
                  <value> val1 </value>
                  </node100> 

            </employee>


    <node100>  is also inside 4-5 nodes (which i have not shown above).

所以我的问题是如何才能读取 first_name 、 last_name 和 tag 。 我的 POJO 类的结构应该是什么?

将 XML 转换为 POJO 的代码

System.out.println( " hello");
ObjectMapper objectMapper = new XmlMapper();
// Reads from XML and converts to POJO
Employees employees = objectMapper.readValue(
        StringUtils.toEncodedString(Files.readAllBytes(Paths.get("C:\\Users\\91895\\Downloads\\File\\XmlFile.xml")), StandardCharsets.UTF_8),
        Employees.class);
System.out.println(employees);

【问题讨论】:

  • 我怎样才能读取 first_name 、 last_name 和 tag - 你通过 tag 发送的内容是什么?
  • 标签是指节点。
  • 如果您还想阅读 node 元素,这意味着您想阅读所有内容。但是你的话just read意味着你想跳过一些元素。你到底想读什么,跳过什么?
  • 是的,你是对的。我没有正确地提出问题。我想跳过除 first_name 、node100 及其子节点以外的所有节点。那么如何创建我的 POJO 类?

标签: java xml jackson jackson-dataformat-xml


【解决方案1】:

在你的类中定义你想从 XML 中读取的元素。要忽略其他元素,请相应配置 ObjectMapper:

objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

【讨论】:

  • 谢谢这是我一直在寻找的。只是怀疑我正在阅读的文件是否正确?因为我不想一次将整个文件加载到内存中。这是一个巨大的文件.
  • 我不想在内存中一次加载整个文件 - 您可以为此使用不同的技术。例如,您可以实现自己的 SAXParser,也可以使用流式 API(参见此处的示例)。然后您可以控制何时创建更多元素。
  • objectMapper.readValue( StringUtils.toEncodedString(Files.readAllBytes(Paths.get("C:\\Users\\91895\\Downloads\\File\\XmlFile.xml")), StandardCharsets.UTF_8), Employees.class); 所以你说目前我正在一次加载整个文件。我应该对 Jackson 使用流 api 吗?你的“你可以使用流 API(见这里的例子)”不起作用.
  • 没有。流 API 而不是 Jackson。该文件将被读取到最后。但是您可能会决定,例如您只创建 5 个对象,您可以忽略任何进一步出现的对象。
  • 如果你有一个像 1TB 这样的大文件,并且想只读取前 100K,那么你也可以实现自己的 InputStream,它在读取 100K 后停止。当然,你必须对相应的异常做出正确的反应。