JAXB @XmlRootElement具有相同的名称

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAXB @XmlRootElement具有相同的名称相关的知识,希望对你有一定的参考价值。

我有一个非常长的XML:

<Author>
    <id></id>
    <name></name>
    <title></title>
    <address></address>
     ....
</Author>

我之前使用JAXB解析XML。

JAXBContext.newInstance(Author.class);

还有我的Author.java

@XmlRootElement(name = "Author")
public class Author {
     private String id;
     private String name;
     private String title;
     private String address;
     ...
}

它运行良好,但我不想每次都将整个XML解析为一个大的Java bean。

所以,我想在下面使用:

创建Commentator.java

@XmlRootElement(name = "Author")
public class Commentator {
     private String id;
     private String name;
     // setters, getters
}

创建Analyst.java

@XmlRootElement(name = "Author")
public class Analyst {
     private String title;
     private String address;
     // setters, getters
}

我写下面的代码进行测试。

JAXBContext context = JAXBContext.newInstance(Analyst.class, Commentator.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
String xml = "<Author> <id>1</id> <name>A</name> <title>B</title> <address>C</address></Author>";
Commentator obj = (Commentator) unmarshaller.unmarshal(new ByteArrayInputStream(xml.getBytes()));
System.out.println(obj);

它将打印正确的结果。

如果我想得到分析师。

Analyst a = (Analyst) unmarshaller.unmarshal(new ByteArrayInputStream(xml.getBytes()));

我会得到例外:java.lang.ClassCastException: com.xxx.Commentator cannot be cast to com.xxx.Analyst

我不确定解析器的这种方式是否正确。但我真的需要这样一个功能。

答案

找到一个快速的方法来做到这一点:

  1. 注册便便。

JAXBContext context = JAXBContext.newInstance(Analyst.class, Commentator.class);

  1. 处理输入。我将str-xml转换为StreamSource。
String xml = "<Author> <id>1</id> <name>A</name> <title>B</title> <address>C</address></Author>";
StreamSource source = new StreamSource(new ByteArrayInputStream(xml.getBytes()));
  1. 创建Unmarshaller。

Unmarshaller unmarshaller = context.createUnmarshaller();

  1. (重要)当你解组数据时,给出第二个参数(你想要解组的那个类)

JAXBElement<Analyst> unmarshal = unmarshaller.unmarshal(source, Analyst.class);

然后,得到你想要的:

Analyst analyst = unmarshal.getValue();

  1. 如果需要另一个pojo。(注意unmarshallersource不能在方法中重复使用)

JAXBElement<Commentator> unmarshal2 = unmarshaller2.unmarshal(source2, Commentator.class);

然后:

Commentator com = unmarshal2.getValue();

没有错误报告和结果是正确的。

另一答案

在我看来,使用相同的@XmlRootElement映射几个Java类是一种有点笨拙的设计。但是,你仍然能够实现你想要的。

你需要不同的JAXBContexts为AnalystCommentator。 因为JAXBContext是一个大对象而JAXBContext.newInstance(...)需要相当长的时间才能执行,所以在JAXBContextvariables中保存这些static实例并重用它们而不是创建新的实例是有意义的:

private static JAXBContext analystContext;
private static JAXBContext commentatorContext;

if (analystContext == null)
    analystContext = JAXBContext.newInstance(Analyst.class);
if (commentatorContext == null)
    commentatorContext = JAXBContext.newInstance(Commentator.class);

因此,您还需要从它们创建不同的Unmarshallers:

Unmarshaller analystUnmarshaller = analystContext.createUnmarshaller();
Unmarshaller commentatorUnmarshaller = commentatorContext.createUnmarshaller();

然后,您可以将相同的XML内容解组到不同的根类:

String xml = "<Author> <id>1</id> <name>A</name> <title>B</title> <address>C</address></Author>";
Analyst analyst = (Analyst) analystUnmarshaller.unmarshal(new ByteArrayInputStream(xml.getBytes()));
Commentator commentator = (Commentator) commentatorUnmarshaller.unmarshal(new ByteArrayInputStream(xml.getBytes()));

以上是关于JAXB @XmlRootElement具有相同的名称的主要内容,如果未能解决你的问题,请参考以下文章

XmlRootElement JAXB

没有由 JAXB 生成的 @XmlRootElement

JAXB注解 @XmlRootElement 及XML文件解析详解

在 JaxB 编组没有 @XmlRootElement 注释的元素时删除 ns2 前缀

没有由JAXB生成的@XmlRootElement

JAXB - Annotations, Top-level Elements: XmlRootElement