2013-12-12 3 views
2

XML 요소의 시퀀스를 "부모"요소 내에있는 한 HashMap에 비 정렬 화하는 방법을 설명하는 기사가 많이 있습니다. 그러나, 나는 루트 요소 바로 아래에있는 아이들과 함께 작동하지 않습니다!JAXB XML 요소를 HashMap에 unmarshal

옵션 1 - 작품 :

<?xml version="1.0" encoding="UTF-8"?> 
<checks> 
    <checks> 
    <check key="check1"/> 
    <check key="check2"/> 
    ...  
    </checks> 
</checks> 

옵션 2 -합니까 하지 일 :

<?xml version="1.0" encoding="UTF-8"?> 
<checks> 
    <check key="check1"/> 
    <check key="check2"/> 
    ... 
</checks> 

확인 :

package com.foo.conf; 

import java.util.Map; 

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

@XmlRootElement(name="checks") 
public class Checks {  
    @XmlJavaTypeAdapter(ChecksAdapter.class) 
    @XmlElement(name="checks") 
    public Map<String, Check> checkMap;  
} 

확인 :

package com.foo.conf; 

import javax.xml.bind.annotation.XmlAttribute; 
import javax.xml.bind.annotation.XmlValue; 

public class Check { 
    @XmlAttribute public String key; 
    @XmlValue public String description; 

    public Check() { } 

    public Check(String key) { 
     this.key = key; 
    } 

    public String getCheckKey() { 
     return this.key; 
    } 
} 

CheckMapType :

package com.foo.conf; 

import java.util.List; 

import javax.xml.bind.annotation.XmlElement; 

class CheckMapType { 
    @XmlElement(name="check") 
    public List<Check> checkList; // = new ArrayList<Check>(); 
} 

ChecksAdapter :

package com.foo.conf; 

import java.util.HashMap; 
import java.util.Map; 

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

final class ChecksAdapter extends XmlAdapter<CheckMapType, Map<String, Check>> { 

    @Override 
    public CheckMapType marshal(Map<String, Check> arg0) throws Exception { 
     return null; 
    } 

    @Override 
    public Map<String, Check> unmarshal(CheckMapType arg0) throws Exception { 
     System.out.println("u: " + arg0.checkList.size()); 
     Map<String, Check> map = new HashMap<String, Check>(); 

     for (Check check : arg0.checkList) { 
      System.out.println(check); 
      map.put(check.key, check); 
     } 
     return map; 
    }  
} 

이 내가 클래스를 생성하는 방법 (일부 더미 테스트 라인)입니다/비 정렬 화 호출 :

JAXBContext jc = JAXBContext.newInstance(Checks.class); 
Unmarshaller u = jc.createUnmarshaller(); 
Checks c = (Checks) u.unmarshal(new File("checks.xml")); 
System.out.println(c.checkMap.size()); 

어떤 아이디어 옵션 # 2를 작동시키는 방법에 대해? 지도 대신 목록을 사용할 때 작동하지만 지정된 키를 사용하여 개체에 액세스해야하므로 HashMap이 필요합니다 ...

힌트를 많이 보내 주시면 감사하겠습니다.

답변

3

참고 : 나는해요명의 사용자와 JAXB (JSR-222) 전문가 그룹의 멤버입니다.

JAXB는 각 오브젝트 관계를 중첩 관계로 처리합니다. MapCollection 대신 Object처럼 처리되므로 사용자가보고있는 동작을 얻게됩니다.

MOXy에는 @XmlPath이라는 XPath 기반 매핑 확장명이 있으며이 사용 사례에 사용할 수 있습니다.귀하의 코멘트에 대한 추가 정보

package com.foo.conf; 

import java.util.Map; 

import javax.xml.bind.annotation.XmlElement; 
import javax.xml.bind.annotation.XmlRootElement; 
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; 
import org.eclipse.persistence.oxm.annotations.XmlPath; 

@XmlRootElement(name="checks") 
public class Checks {  
    @XmlJavaTypeAdapter(ChecksAdapter.class) 
    @XmlPath(".") 
    public Map<String, Check> checkMap;  
} 

+0

매우 유용한 설명 주셔서 감사합니다 - 곧 시도해 보겠습니다. – rawberto

0

어떻게 JAXB 클래스를 생성합니까? 나는 .. 여기

JAXBContext jc = JAXBContext.newInstance(ChecksType.class); 

    Unmarshaller unmarshaller = jc.createUnmarshaller(); 
    ChecksType chksType = (ChecksType) unmarshaller.unmarshal(new File("/path/to/xml")); 

    Marshaller marshaller = jc.createMarshaller(); 
    marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
    marshaller.marshal(chksType, System.out); 

    System.err.println(chksType.getCheck().get(0).getKey()); 

    for (CheckType checkType : chksType.getCheck()) { 
     System.out.println("key = " + checkType.getKey() + ", " + checkType); 
    } 

정확하게 당신이 일을하려고하지만, 아래 아주 간단한 코드는 나를 위해 작동 무엇인지 확실하지 오전 내 JAXB 생성 된 클래스 .. ChecksType (루트 요소)

@XmlAccessorType(XmlAccessType.FIELD) 
    @XmlType(name = "checksType", propOrder = { "check" }) 
    @XmlRootElement(name = "checks") 
    public class ChecksType { 

     @XmlElement(required = true) 
     protected List<CheckType> check; 


     public List<CheckType> getCheck() { 
      if (check == null) { 
      check = new ArrayList<CheckType>(); 
      } 
      return this.check; 
     } 

    } 

그리고 checkType (아이)

@XmlAccessorType(XmlAccessType.FIELD) 
    @XmlType(name = "checkType") 
    public class CheckType { 

     @XmlAttribute(name = "key") 
     protected String key; 


     public String getKey() { 
      return key; 
     } 


     public void setKey(String value) { 
      this.key = value; 
     } 

    } 
+0

감사합니다. 그것은 실제 질문에 대답하지 않지만, ArrayList를 사용하여 작동하지만 HashMap을 사용하지 않는다고 언급 했으므로 필요로합니다. – rawberto