12

次のタイプを定義するスキーマがあります。

<xsd:complexType name="Payload">
   <xsd:sequence>
      <xsd:any namespace="##any" minOccurs="0" maxOccurs="unbounded" processContents="lax"/>
   </xsd:sequence>
</xsd:complexType>

そして、それは次のようなオブジェクトを作成します:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Payload", propOrder = {
    "any"
})
public class Payload {

    @XmlAnyElement(lax = true)
    protected List<Object> any;
}

次に、生成された別のJAXBオブジェクトをそのペイロードに追加して次のようにします。

Class payloadClass = ...;
JAXBContext context = JAXBContext.newInstance( WrapperRequest.class, payloadClass);
...
marshaller.marshal( wrappedRequest );

しかし、動作しないように見えるひどい例外が発生したため、最初にペイロードオブジェクトをXMLにシリアル化してから、それをペイロードの文字列として追加することにしました。

StringWriter writer = new StringWriter();
JAXBContext context = JAXBContext.newInstance( sdoRequest.getClass() );
Marshaller marshaller = context.createMarshaller();
marshaller.marshal(new JAXBElement(new QName("uri", sdoRequest.getClass().getSimpleName()), sdoRequest.getClass(), sdoRequest), writer);
payload.getAny().add( writer.toString() );

そして、これは「java.lang.String」に@XmlRootElementが含まれていないという例外で爆発します。

では、xs:anyの使用はJAXBでどのように機能するのでしょうか?JAXBはペイロードをオブジェクトに変換し、オブジェクト内の何もシリアル化しないため、何も機能したくないようです。これはすべてAxis2の内部にもあるため、この点に到達するのは非常に困難です。

4

3 に答える 3

18

以下に、JAXB(JSR-222)any例を示します。

ペイロード

プロパティには。のany注釈が付けられてい@XmlAnyElement(lax=true)ます。これは、要素がを介してクラスに関連付けられている場合はそのプロパティに対して、そうで@XmlRootElementない@XmlElementDecl場合は対応するオブジェクトのインスタンスを使用してプロパティを設定することを意味しますorg.w3c.dom.Element

package forum13941747;

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

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Payload", propOrder = {
    "any"
})
public class Payload {

    @XmlAnyElement(lax = true)
    protected List<Object> any;

}

Foo

以下は、で注釈が付けられたクラスの例です@XmlRootElement

package forum13941747;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Foo {

}

バー

@XmlRootElement以下は、アノテーションのないクラスの例です。このユースケースでは、で注釈が@XmlElementDecl付けられたファクトリクラス(通常はと呼ばれるObjectFactory)の注釈を活用し@XmlRegistryます。

package forum13941747;

public class Bar {

}

ObjectFactory

以下は、クラスの@XmlElementDeclアノテーションを指定する例です。Bar

package forum13941747;

import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;
import javax.xml.namespace.QName;

@XmlRegistry
public class ObjectFactory {

    @XmlElementDecl(name="bar")
    public JAXBElement<Bar> createBar(Bar bar) {
        return new JAXBElement<Bar>(new QName("bar"), Bar.class, bar);
    }

}

input.xml

以下は、この例で使用する入力ドキュメントです。プロパティに対応する3つの要素がありanyます。1つ目は、クラスの@XmlRootElement注釈に対応します。Foo2番目@XmlElementDeclはクラスの注釈に対応しBar、3番目はどのドメインクラスにも対応していません。

<?xml version="1.0" encoding="UTF-8"?>
<payload>
    <foo/>
    <bar/>
    <other/>
</payload>

デモ

以下のデモコードでは、入力ドキュメントのマーシャリングを解除し、結果のanyプロパティでオブジェクトのクラスを出力してから、オブジェクトをマーシャリングしpayloadてXMLに戻します。

package forum13941747;

import java.io.File;
import javax.xml.bind.*;

public class Demo {

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

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("src/forum13941747/input.xml");
        Payload payload = (Payload) unmarshaller.unmarshal(xml);

        for(Object o : payload.any) {
            System.out.println(o.getClass());
        }

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

}

出力

以下は、デモコードの実行からの出力です。anyプロパティ内のオブジェクトに対応するクラスに注意してください。要素はクラスのfooインスタンスになりました。要素は、のインスタンスFooを保持するのインスタンスになりました。要素はのインスタンスになりました。barJAXBElementBarotherorg.w3c.dom.Element

class forum13941747.Foo
class javax.xml.bind.JAXBElement
class com.sun.org.apache.xerces.internal.dom.ElementNSImpl
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<payload>
    <foo/>
    <bar/>
    <other/>
</payload>
于 2012-12-19T11:09:26.603 に答える
1

以下のようにオブジェクトをマシェル化するためにオブジェクトファクトリを利用します。DemoType.javaに@XmlRootElementを含める必要はありません。

DemoType demoServiceRequest = new DemoType();
ObjectFactory obDemo = new ObjectFactory();  
Request requestObject = new Request();     
requestObject.setAny(obDemo.createDemo(demoServiceRequest));

そして、@ XmlSeeAlso({DemoType.class})のようなRequest.javaにDemoTypeクラスを追加します

于 2015-06-09T22:25:03.517 に答える
0

ペイロードがXML文字列の場合、以下のコードを使用してまったく同じ問題を解決することができました。

import javax.xml.parsers.DocumentBuilderFactory;

//...

String XMLPAYLOAD = "...";

Payload payload = new ObjectFactory().createPayload();
try {
    payload.setAny(DocumentBuilderFactory
           .newInstance()
           .newDocumentBuilder()
           .parse(new InputSource(new StringReader(XMLPAYLOAD)))
           .getDocumentElement());
} catch (Exception e) {
    e.printStackTrace();
}

//...
于 2019-05-23T16:06:25.833 に答える