2011-05-13 2 views
3

자바 XML 바인딩에 초보자 나는 도전에 직면 중입니다.특정 깊이에 Java XML 바인딩을 사용하여 objectgraph를 마샬링하는 방법은 무엇입니까?

도메인 모델이 생성되고이 도메인을 XML 구조로 마샬링하는 시나리오가 있다고 가정 해 보겠습니다.

지금 내가 다른 비 정렬 화 경로의를 제공하고자 :

  1. 마샬 전체 개체 그래프 [여기 아무 문제]를
  2. 마샬 objectgraph 특정 깊이까지! [도전]

나는 복잡한 문제를 야기하지 않고이를 해결하는 방법에 대해 좋은 길을 찾아 낼 수 없다. 도메인의 사본을 만들어 나중에 수동으로 만들 수는 있지만 그게 옳은 생각은 아닙니다. 다른 솔루션을 사용할 수 있습니까?

답변

2

당신은이 동작을 얻기 위해 (때문에) XmlAdapter와 Marshal.Listener을 활용할 수 :

Marshal.Listener은 우리가 정렬 화하는 트리의 깊이를 추적하기 위해 설정됩니다

데모. 또한 깊이 수신기를 인식하는 런타임 수준의 XmlAdapter를 설정합니다. 이러한 어댑터는 원하는 깊이에 도달하면 null을 반환하기 시작합니다.

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

public class Demo { 

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

     Root rootA = new Root(); 
     rootA.setName("A"); 

     Root rootB = new Root(); 
     rootB.setName("B"); 
     rootA.setChild(rootB); 

     Root rootC = new Root(); 
     rootC.setName("C"); 
     rootB.setChild(rootC); 

     Root rootD = new Root(); 
     rootD.setName("D"); 
     rootC.setChild(rootD); 

     Root rootE = new Root(); 
     rootE.setName("E"); 
     rootD.setChild(rootE); 

     Marshaller marshaller = jc.createMarshaller(); 
     marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 

     DepthListener depthListener = new DepthListener(3); 
     marshaller.setListener(depthListener); 
     marshaller.setAdapter(new RootAdapter(depthListener)); 
     marshaller.marshal(rootA, System.out); 
    } 

} 

DepthListener

이 클래스의 목적은 현재의 깊이를 추적 할 것입니다.

import javax.xml.bind.Marshaller; 

public class DepthListener extends Marshaller.Listener { 

    private int targetDepth; 
    private int currentDepth = 0; 

    public DepthListener(int depth) { 
     this.targetDepth = depth; 
    } 

    @Override 
    public void beforeMarshal(Object source) { 
     currentDepth++; 
    } 

    @Override 
    public void afterMarshal(Object source) { 
     currentDepth--; 
    } 

    public boolean isMarshalDepth() { 
     return currentDepth <= targetDepth; 
    } 

} 

RootAdapter

(때문에) XmlAdapter의 목적은 원하는 깊이 마샬링 프로세스를 중지 도달했을 때 널 (null)을 반환 시작한다.

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

public class RootAdapter extends XmlAdapter<Root, Root> { 

    private DepthListener depthListener; 

    public RootAdapter() { 
    } 

    public RootAdapter(DepthListener depthListener) { 
     this.depthListener = depthListener; 
    } 

    @Override 
    public Root unmarshal(Root root) throws Exception { 
     return root; 
    } 

    @Override 
    public Root marshal(Root root) throws Exception { 
     if(depthListener != null && !depthListener.isMarshalDepth()) { 
      return null; 
     } 
     return root; 
    } 

} 

루트

다음은 @XmlJavaTypeAdapter 주석을 통해 도메인 개체에 (때문에) XmlAdapter를 지정하는 방법을 보여줍니다

다음은입니다

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

@XmlRootElement 
@XmlJavaTypeAdapter(RootAdapter.class) 
@XmlType(propOrder={"name", "child"}) 
public class Root { 

    private String name; 
    private Root child; 

    public String getName() { 
     return name; 
    } 

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

    public Root getChild() { 
     return child; 
    } 

    public void setChild(Root report) { 
     this.child = report; 
    } 

} 

출력 데모 코드의 출력 :

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<root> 
    <name>A</name> 
    <child> 
     <name>B</name> 
     <child> 
      <name>C</name> 
     </child> 
    </child> 
</root> 
관련 문제