2016-04-27 11 views
0

xcj.xsd)とwsimport.wsdl)定義を使用して生成されたプロキシを使用して呼び出す必要があるWebサービスがあります。外部(すなわち編集不可)、巨大で絶えず変化する(生成されたクラスを手で調整することはできません)JAX-WS(JAXB)と混合型xs:anyTypeのアンマーシャリング

xs:anyTypeの要素は、mixed="true"であり、以下のサンプルと同様です。

<Foo type="Bar"> 
    <id>123</id> 
</Foo> 

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
    <xs:element name="Foo"> 
     <xs:complexType> 
      <xs:complexContent mixed="true"> 
       <xs:extension base="xs:anyType"> 
        <xs:attribute name="type" type="xs:string"/> 
       </xs:extension> 
      </xs:complexContent> 
     </xs:complexType> 
    </xs:element> 

    <xs:element name="Bar"> 
     <xs:complexType> 
      <xs:sequence> 
       <xs:element name="id" type="xs:int"/> 
       <xs:element name="name" type="xs:string"/> 
      </xs:sequence> 
     </xs:complexType> 
    </xs:element> 
</xs:schema> 

xjc/wsimport

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "", propOrder = { "content" }) 
@XmlRootElement(name = "Foo") 
public class Foo { 
    @XmlMixed 
    @XmlAnyElement 
    protected List<Object> content; 
    @XmlAttribute(name = "type") 
    protected String type; 
    @XmlAnyAttribute 
    private Map<QName, String> otherAttributes = new HashMap<QName, String>(); 

私ができるマーシャルDocument.getChildNodes()を使用して、ルートレス形態にFooのオブジェクトを(私はクリーンな方法を見つけること気にしないだろうが)、以下のようにFooを生成し、私はどのようにレスポンスのcontentリスト(プロキシが完了した後にArrayList<ElementNSImpl>)のリストをアンマーシャルするかを厳密にタイプされたBarに解くことができませんか?

public static void main(String[] args) throws Exception { 
    Foo foo = new Foo(); 
    foo.type = "Bar"; 

    Bar bar = new Bar(); 
    bar.id = 123; 

    JAXBContext context = JAXBContext.newInstance(Foo.class, Bar.class); 
    Marshaller marshaller = context.createMarshaller(); 
    marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 

    Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); 
    marshaller.marshal(bar, document); 

    NodeList nodes = document.getFirstChild().getChildNodes(); 
    foo.content = IntStream.range(0, nodes.getLength()).mapToObj(nodes::item).collect(Collectors.toList()); 

    StringWriter writer = new StringWriter(); 
    marshaller.marshal(foo, writer); 
    System.out.println(writer); 

    Unmarshaller unmarshaller = context.createUnmarshaller(); 

    // ??? 
    unmarshaller.unmarshal(foo.content, Bar.class); 
} 

答えて

0

私はそれを解決したと思います。だれにアップアップしても清潔な解決策が出ます。

public static List<Object> marshal(Object value) { 
    try { 
     Class<?> type = value.getClass(); 
     if (type.isAnonymousClass()) 
      type = type.getSuperclass(); 

     Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); 
     Marshaller marshaller = JAXBContext.newInstance(type).createMarshaller(); 
     marshaller.marshal(new JAXBElement<>(QName.valueOf("root"), Object.class, value), document); 

     NodeList nodes = document.getDocumentElement().getChildNodes(); 
     return IntStream.range(0, nodes.getLength()).mapToObj(nodes::item).collect(Collectors.toList()); 
    } catch (Exception e) { 
     throw new RuntimeException(e); 
    } 
} 

public static <T> T unmarshal(List<Object> content, Map<QName, String> attributes, Class<T> type) { 
    try { 
     Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); 
     document.appendChild(document.createElement("root")); 

     if (attributes != null) 
      attributes.forEach((q, s) -> document.getDocumentElement().setAttribute(q.getLocalPart(), s)); 

     if (content != null) 
      content.forEach(o -> document.getDocumentElement().appendChild(document.importNode((Node) o, true))); 

     Unmarshaller unmarshaller = JAXBContext.newInstance(type).createUnmarshaller(); 
     return unmarshaller.unmarshal(document, type).getValue(); 
    } catch (Exception e) { 
     throw new RuntimeException(e); 
    } 
} 
関連する問題