2012-12-20 34 views
11

Tôi làm cách nào để hướng dẫn JAXB xử lý việc này?Làm thế nào để unmarshall lặp đi lặp lại các lớp lồng nhau với 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; 
} 

này không hoạt động ... allChildren trống.

Trả lời

13

Bạn có thể thay đổi mô hình của bạn và làm như sau:

gốc

@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; 
} 

CẬP NHẬT

Có thể tránh được những tầng lớp phụ huynh?

Có một vài cách khác nhau để thực hiện điều này:

OPTION # 1 - Bất kỳ thực hiện JAXB sử dụng XmlAdapter

Bạn có thể sử dụng một XmlAdapter cho hầu như thêm trong lớp 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; 
    } 

} 

gốc

Các @XmlJavaTypeAdapter chú thích được sử dụng để tham khảo các 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; 

} 

Child

import javax.xml.bind.annotation.*; 

@XmlAccessorType(XmlAccessType.FIELD) 
public class Child { 

    @XmlAttribute 
    int id; 

    @XmlAttribute 
    String name; 

} 

OPTION # 2 - Sử dụng EclipseLink JAXB (MOXY)

Nếu bạn đang sử dụng EclipseLink JAXB (MOXy) như thực hiện JAXB (JSR-222) của bạn thì bạn có thể làm như sau (Lưu ý : Tôi là trưởng nhóm MOXy):

gốc

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

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

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

} 

Child

@XmlPath chú thích MOXY của hoạt động khá giống như cách bạn đang cố gắng sử dụng @XmlElement chú thích trong bài viết của bạn.

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; 

} 

Để biết thêm thông tin

+0

Có thể tránh lớp cha mẹ không? – Stephan

+4

+1 Luôn yên tâm khi tôi độc lập đưa ra giải pháp giống hệt như một chuyên gia được công nhận trong lĩnh vực :-) –

+1

@IanRoberts - Tôi cũng đã +1 câu trả lời của bạn :). –

1

Bạn có thể thử sử dụng XmlElementWrapper chú thích nhưng tôi không chắc chắn làm thế nào nó sẽ làm việc với nhiều nút wrapper:

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

tôi chỉ nhận được một đứa trẻ và không phải tất cả trẻ em. – Stephan

0

Hãy thử điều này

@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

Có, nhưng cha mẹ ở đây chỉ là một thủ thuật, chỉ là một lớp học riêng. Quan trọng nhất là chúng tôi có Danh sách không phải Danh sách

2

Bạn sẽ phải tạo ra một lớp đại diện cho yếu tố <parent>, chẳng hạn như

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

Sau đó, bạn có thể tạo ra một loại bộ chuyển đổi

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; 
    } 
} 

và sử dụng này trên lớp rễ

@XmlRootElement 
public class Root { 
    @XmlElement(name="parent") 
    @XmlJavaTypeAdapter(ParentToChildAdapter.class) 
    List<Child> allChildren; 
} 
Các vấn đề liên quan