Java 如何在加载到pojo时跳过xml元素(在xstream/jaxb中)

Java 如何在加载到pojo时跳过xml元素(在xstream/jaxb中),java,xml,xml-parsing,jaxb,xstream,Java,Xml,Xml Parsing,Jaxb,Xstream,我有一个非常大且复杂的xml,我只想将选定的字段加载到我的对象中。 我尝试过xstream,但我理解的是我的xml结构必须与我的pojo相似。 我提供样品I/p和o/p,以便更好地理解 <note> <to>Tove</to> <from>Jani</from> <heading>Reminder</heading> <body>Don't forget me this weekend!</bo

我有一个非常大且复杂的xml,我只想将选定的字段加载到我的对象中。 我尝试过xstream,但我理解的是我的xml结构必须与我的pojo相似。 我提供样品I/p和o/p,以便更好地理解

<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
问题是如何在将xml元素加载到pojo时跳过它?

您可以使用它。Jackson可能更出名的是
JSON
序列化/反序列化,但它有一个XML扩展

如果您的XML文件很大,请查看上面的链接,了解如何部分/增量地读取它以获得最佳性能

下面是一个示例,说明如何在不希望反序列化的字段上使用
@JsonIgnore
注释,仅读取属性的子集:

@JacksonXmlRootElement(localName = "jokes")
class Jokes {

    @JacksonXmlProperty(localName = "joke")
    @JacksonXmlElementWrapper(useWrapping = false)
    private Joke[] jokes;

    // getter, setter omitted
}

class Joke {
    @JacksonXmlProperty(isAttribute = true)
    long id;

    @JacksonXmlProperty(localName = "title")
    String title;

    @JsonIgnore
    String author;

    @JacksonXmlProperty(localName = "like")
    long like;

    @JsonIgnore
    String content;

    public String toString() {
        return Arrays.stream(new Object[] {id, title, author, like, content})
                .map(o -> o!=null ? o.toString() : "EMPTY")
                .collect(Collectors.joining(", ", "[", "]"));
    }

    // getters, setters omitted
}
使用示例文件:

<jokes>
    <joke id="123">
        <title>C'est l'histoire d'un mec</title>
        <author>Coluche</author>
        <content>Blah blah blah</content>
        <like>4509</like>
    </joke>
    <joke id="777">
        <title>Si j'ai bien tout lu freud</title>
        <author>Coluche</author>
        <content>Blah blah blah</content>
        <like>345</like>
    </joke>
</jokes>
输出为(注意空字段):

[123,C'est l'historire d'un mec,EMPTY,4509,EMPTY]
[777,Si j'ai bien tout lu freud,空,345,空]

您还可以创建一个只包含所需字段的pojo,然后不使用
@JsonIgnore
。为此,必须通知
XmlMapper
忽略未知的XML属性

    XmlMapper mapper = new XmlMapper();
    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

编辑 您希望pojo只包含几个字段的完整示例如下:

假设我们有一个只有
id
title
的pojo:

class Joke {
    @JacksonXmlProperty(isAttribute = true)
    long id;

    @JacksonXmlProperty(localName = "title")
    String title;
    
    public String toString() {
        return new StringBuffer().append('[')
                .append(id).append(',')
                .append(title).append(']').toString();
    }
    // getters setters 
}
使用上述xml文件执行以下
main()

公共类XmlJokerReader{

    public static void main(String[] args) throws JsonProcessingException, IOException {
        XmlMapper mapper = new XmlMapper();
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        Jokes jokesDoc = mapper.readValue(new File("./data/jokes.xml"), Jokes.class);
        for (Joke joke : jokesDoc.getJokes()) {
           System.out.println(joke.toString());
        }
    }
}
将提供:

[123,C'est l'historire d'un mec]
[777,Si j'ai bien tout lu freud]

您可以使用.Jackson进行序列化/反序列化,它可能以
JSON
序列化/反序列化而闻名,但它有一个XML扩展

如果您的XML文件很大,请查看上面的链接,了解如何部分/增量地读取它以获得最佳性能

下面是一个示例,说明如何在不希望反序列化的字段上使用
@JsonIgnore
注释,仅读取属性的子集:

@JacksonXmlRootElement(localName = "jokes")
class Jokes {

    @JacksonXmlProperty(localName = "joke")
    @JacksonXmlElementWrapper(useWrapping = false)
    private Joke[] jokes;

    // getter, setter omitted
}

class Joke {
    @JacksonXmlProperty(isAttribute = true)
    long id;

    @JacksonXmlProperty(localName = "title")
    String title;

    @JsonIgnore
    String author;

    @JacksonXmlProperty(localName = "like")
    long like;

    @JsonIgnore
    String content;

    public String toString() {
        return Arrays.stream(new Object[] {id, title, author, like, content})
                .map(o -> o!=null ? o.toString() : "EMPTY")
                .collect(Collectors.joining(", ", "[", "]"));
    }

    // getters, setters omitted
}
使用示例文件:

<jokes>
    <joke id="123">
        <title>C'est l'histoire d'un mec</title>
        <author>Coluche</author>
        <content>Blah blah blah</content>
        <like>4509</like>
    </joke>
    <joke id="777">
        <title>Si j'ai bien tout lu freud</title>
        <author>Coluche</author>
        <content>Blah blah blah</content>
        <like>345</like>
    </joke>
</jokes>
输出为(注意空字段):

[123,C'est l'historire d'un mec,EMPTY,4509,EMPTY]
[777,Si j'ai bien tout lu freud,空,345,空]

您还可以创建一个只包含所需字段的pojo,然后不使用
@JsonIgnore
。为此,必须通知
XmlMapper
忽略未知的XML属性

    XmlMapper mapper = new XmlMapper();
    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

编辑 您希望pojo只包含几个字段的完整示例如下:

假设我们有一个只有
id
title
的pojo:

class Joke {
    @JacksonXmlProperty(isAttribute = true)
    long id;

    @JacksonXmlProperty(localName = "title")
    String title;
    
    public String toString() {
        return new StringBuffer().append('[')
                .append(id).append(',')
                .append(title).append(']').toString();
    }
    // getters setters 
}
使用上述xml文件执行以下
main()

公共类XmlJokerReader{

    public static void main(String[] args) throws JsonProcessingException, IOException {
        XmlMapper mapper = new XmlMapper();
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        Jokes jokesDoc = mapper.readValue(new File("./data/jokes.xml"), Jokes.class);
        for (Joke joke : jokesDoc.getJokes()) {
           System.out.println(joke.toString());
        }
    }
}
将提供:

[123,C'est l'historire d'un mec]
[777,Si j'ai bien tout lu freud]


但无论如何,您得到的内容字段值为空,并且您已经创建了类似于xml的pojo结构。我希望pojo中只包含必需的xml字段。我不希望在pojo中不必要地声明字段。您还没有理解最后一部分:您可以拥有一个pojo,其中只包含您想要的属性。为此,您需要设置
DeserializationFeature.UNKNOWN属性上的失败
false
。事实上,
EMPTY
只是我放入
toString()中的
字符串
方法。请参见编辑以获取您确切需要的示例。假设在您的示例中,author元素有子元素,如id、name、address、图书列表等。因此,我可以使用@JacksonXmlProperty直接获取author name,而无需将author作为单独的pojo?您必须使用propert定义单独的pojo
author
y
name
。有可能通过指定元素的路径来展平xml树,这可能很有趣。这可能是JacksonXML发展的一些建议……但无论如何,您得到的内容字段值为空,并且您创建了类似于xml的pojo结构。我希望在我的p中只包含必需的xml字段ojo.我不想在pojo中不必要地声明字段..你还没有理解最后一部分:你可以拥有一个只包含你想要的属性的pojo。为此,你需要设置
反序列化功能。将未知属性
的失败设置为
false
。事实上,
空的
只是我放在<代码>toString()
方法。请参见编辑以获取您确切需要的示例。假设在您的示例中,author元素有子元素,如id、name、address、图书列表等。因此,我可以使用@JacksonXmlProperty直接获取author name,而无需将author作为单独的pojo?您必须使用propert定义单独的pojo
author
y
name
。可以通过指定元素的路径来展平xml树,这可能很有趣。这可能是JacksonXML发展的一些建议。。。