@XmlElements помечены @XmlJavaTypeAdapters? - PullRequest
7 голосов
/ 22 мая 2011

У меня такая ситуация

@XmlType(name ="", propOrder={"value"})
@XmlRootElement(name = "compound")
public class Compound extends Value {
  @XmlElements({
  @XmlElement(name="simple", type=Simple.class),
  @XmlElement(name="compound", type=Compound.class)
  })
  protected List<Value> value;
  // ...
}

Таким образом, соединение - это список как простых, так и / или сложных.Оба расширяются от значения, определенного как

public abstract class Value implements Serializable {}

Simple - это класс, помеченный с помощью адаптера для маршалирования / демаршалирования в / из простой строки

@XmlJavaTypeAdapter(SimpleAdapter.class)
public class Simple extends Value {
  private java.lang.String simple;
  // ...
}

Соединению не нужен адаптер.

Проблема в том, что, если я использую Simple 'as is', он правильно маршалирует / unmarshals как

<simple>my.text.here</simple>

, но если я использую его внутри Compound, он выдает что-то вроде

<compound>
  //...
  <simple>
    <value>my.text.here</value>
  </simple>
  //...
</compound>

И мне просто интересно, почему ... Я что-то пропустил?Как я могу удалить это «значение»?Мне кажется, что адаптер вообще не используется, возможно ли использовать адаптеры в типах, помеченных внутри @XmlElements?

EDIT

После нескольких тестов я обнаружилчто проблема может быть в том, как я обрабатываю простой экземпляр.Поэтому я упростил свой начальный вопрос следующим образом:

Учитывая класс Simple, например

@XmlRootElement("simple")
public class Simple {
  private java.lang.String innerText;
  // getters/setters
}

, как я могу получить маршаллированный вывод, такой как

<simple>
  my.inner.text.here
</simple>

вместо

<simple>
  <value>my.inner.text.here</value>
</simple>

?

Ответы [ 2 ]

2 голосов
/ 24 мая 2011

Звучит так, как будто вы хотите, чтобы private java.lang.String innerText; было значением @XmlValue вашего простого класса.Попробуйте аннотировать String in Simple с помощью тега @XmlValue:

@XmlRootElement("simple")
public class Simple {
  @XmlValue
  private java.lang.String innerText;
  //getters/setters
}

Или, если вы использовали аннотации в своем методе получения (который, как я полагаю, основан на выводе XML в вопросе, измените свой тег @XmlElement натег @XmlValue:

@XmlValue
public java.lang.String getInnerText() {
  return innerText;
}

Когда я делаю это, я получаю вывод, который вы ищете в отредактированном вопросе.

0 голосов
/ 24 мая 2011

Ответ , данный bamana , верен, однако вы видите исключение из-за ошибки в эталонной реализации JAXB. Эта ошибка также существовала в EclipseLink JAXB (MOXy) , но была исправлена ​​в потоке 2.3.0, ее можно скачать здесь:

В качестве обходного пути вы можете использовать подход XmlAdapter, который был в вашем первоначальном вопросе:

SimpleAdapter

import javax.xml.bind.annotation.adapters.XmlAdapter;

public class SimpleAdapter extends XmlAdapter<String, Simple> {

    @Override
    public Simple unmarshal(String v) throws Exception {
        Simple simple = new Simple();
        simple.setSimple(v);
        return simple;
    }

    @Override
    public String marshal(Simple v) throws Exception {
        return v.getSimple();
    }

}

Simple

import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

@XmlJavaTypeAdapter(SimpleAdapter.class)
public class Simple extends Value {
    private java.lang.String simple;

    public java.lang.String getSimple() {
        return simple;
    }

    public void setSimple(java.lang.String simple) {
        this.simple = simple;
    }

}

Compound

import java.util.List;

import javax.xml.bind.annotation.*;

@XmlRootElement(name = "compound")
@XmlAccessorType(XmlAccessType.FIELD)
public class Compound extends Value {
    @XmlElements({ @XmlElement(name = "simple", type = Simple.class),
            @XmlElement(name = "compound", type = Compound.class) })
    protected List<Value> value;

    public List<Value> getValue() {
        return value;
    }

    public void setValue(List<Value> value) {
        this.value = value;
    }

}

Значение

import java.io.Serializable;

public abstract class Value implements Serializable {}

Демо

import java.io.File;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Compound.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Compound compound = (Compound) unmarshaller.unmarshal(new File("input.xml"));
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(compound, System.out);
    }

}

Input.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<compound>
    <simple>
        <simple>FOO</simple>
    </simple>
    <compound/>
</compound>
...