2012-12-20 14 views
11

Come posso chiedere a JAXB di elaborarlo?Come annullare l'emulazione di classi nidificate ripetute con JAXB?

XML

<root> 
<parent> 
    <child id="1" name="foo" /> 
</parent> 
<parent> 
    <child id="3" name="foo2" /> 
</parent> 
<parent> 
    <child id="4" name="bar2" /> 
</parent> 
<parent> 
    <child id="2" name="bar" /> 
</parent> 
</root> 

Root.java

@XmlRootElement 
public class Root { 
    @XmlElement(name="parent/child") 
    List<Child> allChildren; 
} 

Questo non funziona ... allChildren è vuota.

risposta

13

si potrebbe cambiare il vostro modello e procedere come segue:

Root

@XmlRootElement 
@XmlAccessorType(XmlAccessType.FIELD) 
public class Root { 
    @XmlElement(name="parent") 
    List<Parent> allParents; 
} 

Parent

@XmlAccessorType(XmlAccessType.FIELD) 
public class Parent { 
    @XmlElement(name="child") 
    List<Child> allChildren; 
} 

UPDATE

E 'possibile evitare la classe padre?

Ci sono un paio di modi diversi per ottenere questo risultato:

OPZIONE # 1 - qualsiasi implementazione JAXB utilizzando XMLAdapter

È possibile usare un XMLAdapter praticamente aggiungere nella classe Parent.

ChildAdapter

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

public class ChildAdapter extends XmlAdapter<ChildAdapter.Parent, Child> { 

    public static class Parent { 
     public Child child; 
    } 

    @Override 
    public Parent marshal(Child v) throws Exception { 
     Parent parent = new Parent(); 
     parent.child = v; 
     return parent; 
    } 

    @Override 
    public Child unmarshal(Parent v) throws Exception { 
     return v.child; 
    } 

} 

Root

Il @XmlJavaTypeAdapter annotazione viene utilizzato per fare riferimento alla XmlAdapter.

import java.util.List; 
import javax.xml.bind.annotation.*; 
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; 

@XmlRootElement 
@XmlAccessorType(XmlAccessType.FIELD) 
public class Root { 

    @XmlElement(name="parent") 
    @XmlJavaTypeAdapter(ChildAdapter.class) 
    List<Child> allChildren; 

} 

Bambino

import javax.xml.bind.annotation.*; 

@XmlAccessorType(XmlAccessType.FIELD) 
public class Child { 

    @XmlAttribute 
    int id; 

    @XmlAttribute 
    String name; 

} 

OPZIONE # 2 - Utilizzare EclipseLink JAXB (moxy)

Se si utilizza EclipseLink JAXB (MOXy) come JAXB (JSR-222) implementazione allora si potrebbe procedere come segue (nota : I'm the MOXy lead):

Root

import java.util.List; 
import javax.xml.bind.annotation.*; 

@XmlRootElement 
@XmlAccessorType(XmlAccessType.FIELD) 
public class Root { 

    @XmlElement(name="parent") 
    List<Child> allChildren; 

} 

Bambino

@XmlPath annotazione di moxy funziona più o meno il modo in cui si sta tentando di utilizzare la @XmlElement annotazioni nel tuo post.

import javax.xml.bind.annotation.*; 
import org.eclipse.persistence.oxm.annotations.XmlPath; 

@XmlAccessorType(XmlAccessType.FIELD) 
public class Child { 

    @XmlPath("child/@id") 
    int id; 

    @XmlPath("child/@name") 
    String name; 

} 

Per ulteriori informazioni

+0

È possibile evitare la classe genitore? – Stephan

+4

+1 E 'sempre rassicurante quando provo autonomamente la stessa soluzione di un esperto riconosciuto nel campo :-) –

+1

@IanRoberts - I + 1ed anche la tua risposta :). –

1

Si potrebbe provare a utilizzare il XmlElementWrapper di annotazione, ma io non sono sicuro di come dovrebbe funzionare con più nodi involucro:

@XmlRootElement 
public class Root { 
    @XmlElementWrapper(name="parent") 
    @XmlElement(name="child") 
    List<Child> allChildren; 
} 
+0

I prendi solo un bambino e non tutti i bambini. – Stephan

0

Prova questo

@XmlRootElement 
class Root { 
    List<Child> allChildren = new ArrayList<Child>(); 

    private static class Parent { 
     @XmlElement 
     Child child; 
    } 

    @XmlElement 
    public void setParent(Parent p) { 
     allChildren.add(p.child); 
    } 
} 
+0

Sì, ma Parent è solo un trucco, solo una classe privata. La cosa più importante è che abbiamo la lista non la lista

2

Si dovrà creare una classe che rappresenta l'elemento <parent>, come ad esempio

@XmlAccessorType(XmlAccessType.FIELD) 
public class Parent { 
    @XmlElement(name="child") 
    Child child; 
} 

È quindi possibile creare un adattatore di tipo

public class ParentToChildAdapter extends XmlAdapter<Parent, Child> { 
    public Parent marshal(Child c) { 
    Parent p = new Parent(); 
    p.child = child; 
    return p; 
    } 

    public Child unmarshal(Parent p) { 
    return p.child; 
    } 
} 

e utilizzare questo sulla classe radice

@XmlRootElement 
public class Root { 
    @XmlElement(name="parent") 
    @XmlJavaTypeAdapter(ParentToChildAdapter.class) 
    List<Child> allChildren; 
} 
Problemi correlati