JAXB @XmlRootElement с тем же именем - PullRequest
0 голосов
/ 07 сентября 2018

У меня очень длинный 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-бин.

Итак, я хочу использовать следующий способ:

Создать 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

Я не уверен, что этот способ верен парсеру. Но мне действительно нужен такой функционал.

Ответы [ 2 ]

0 голосов
/ 18 сентября 2018

Просто найдите быстрый способ сделать это:

  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. (Обратите внимание, что unmarshaller & source не может быть повторно использован в методе)

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

А потом:

Commentator com = unmarshal2.getValue();

Нет сообщения об ошибке и результат правильный.

0 голосов
/ 10 сентября 2018

На мой взгляд, несколько неуклюжий дизайн состоит в том, чтобы отображать несколько классов Java с одинаковым @XmlRootElement.Но, тем не менее, вы все равно можете достичь того, что вы хотите.

Вам нужны разные JAXBContext s для Analyst и Commentator.
И поскольку JAXBContext - это большой объект, а JAXBContext.newInstance(...) занимает довольно много времени для выполнения, это имеет смыслчтобы сохранить эти JAXBContext экземпляры в 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);

И, следовательно, вам также понадобятся различные Unmarshaller созданные из них:

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()));
...