JAXB unmarshalling на основе родственных элементов - PullRequest
0 голосов
/ 23 февраля 2010

У меня есть следующий фрагмент XML (который находится вне моего контроля):

<item>
  <name>Name</name>
  <category>1</category>
  <subcategory>2</subcategory>
</item>

Я бы хотел, чтобы <subcategory> был переведен в класс, который выглядит следующим образом:

public class SubCategory {
  private Category parent;
  private int code;
  private String name;

  public SubCategory(int code, Category parent){
    this.code = code;
    this.parent = parent;
    this.name = lookupName(code);
  }

  // Getters, setters and lookupName(int) here
}

Другими словами, объект, являющийся результатом тега <category>, должен быть передан объекту, являющемуся результатом элемента <subcategory>.

Как я могу это сделать? Это вообще возможно? Я знаю о XmlAdapter, но не вижу способа завладеть родителем.

Я бы предпочел, чтобы это делалось в конструкторе, поэтому экземпляр никогда не может находиться в недопустимом состоянии, но я остановлюсь на другом решении, если мне не нужно вручную устанавливать родитель для каждого SubCategory.

Ответы [ 3 ]

2 голосов
/ 23 февраля 2010

JAXB не сделает это за вас. XmlAdapter не подходит для этой проблемы. Когда структура класса значительно отличается от структуры XML, вам потребуется выполнить дополнительный уровень преобразования, либо до привязки JAXB (с XSLT), либо после привязки JAXB (с использованием Java).

Последний вариант намного проще. Вам понадобится класс, представляющий структуру XML, и маршрут преобразования, который превращает экземпляры, которые связывают класс, в экземпляры желаемой структуры.

2 голосов
/ 23 февраля 2010

Вы можете сделать это с XMLAdapter, если вы адаптируете Item вместо SubCategory.

ItemAdapter.java:

public class ItemAdapter extends XmlAdapter<ItemProxy, Item>
{
    @Override
    public ItemProxy marshal( Item v ) throws Exception
    {
        ItemProxy proxy = new ItemProxy();

        proxy.setCategory( v.getCategory().getCode() );
        proxy.setSubcategory( v.getSubCategory().getCode() );
        proxy.setName( v.getName() );

        return proxy;
    }

    @Override
    public Item unmarshal( ItemProxy v ) throws Exception
    {
        Item item = new Item();

        Category category = new Category( v.getCategory() );
        SubCategory subCategory = new SubCategory( v.getSubcategory(), category );

        item.setName( v.getName() );
        item.setCategory( category );
        item.setSubCategory( subCategory );

        return item;
    }
}

ItemProxy.java:

@XmlRootElement( name = "item" )
public class ItemProxy
{
    private String name;
    private int category;
    private int subcategory;

    @XmlElement
    public String getName()
    {
        return name;
    }

    @XmlElement
    public int getCategory()
    {
        return category;
    }

    @XmlElement
    public int getSubcategory()
    {
        return subcategory;
    }

    public void setName( String name )
    {
        this.name = name;
    }

    public void setCategory( int category )
    {
        this.category = category;
    }

    public void setSubcategory( int subcategory )
    {
        this.subcategory = subcategory;
    }
}
0 голосов
/ 23 февраля 2010

Один способ, которым я могу думать о том, как это сделать, - написать некоторый XSLT, который преобразует XML в нечто более простое для отображения в JAXB. Хотя это, вероятно, сработает, это дополнительный шаг, который я бы предпочел избежать.

...