6

自分で作成したものではなく、別のパーティから受け取った XSD があります。したがって、相手との互換性を確保する必要があるため、この XSD を変更することはできません。

シンプルバインディングモードを使用してXJC 2.2およびJAXB 2.2を使用して、空のhello要素内にルート要素を作成したいと考えています。しかし、マーシャリングすると、余分な名前空間のがらくたがたくさん発生します。私には不要に見えます。(ただし、動作しますが、送信するデータが増えます...)

XSD ルート要素:

<element name="epp">
        <complexType>
            <choice>
                <element name="greeting" type="epp:greetingType" />
                <element name="hello" />
                <element name="command" type="epp:commandType" />
                <element name="response" type="epp:responseType" />
                <element name="extension" type="epp:extAnyType" />
            </choice>
        </complexType>
    </element>

Java コード:

Epp epp = new Epp(); 
epp.setHello("");

マーシャリングされた結果:

<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
     <hello xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string"></hello>
</epp>

望ましい結果:

<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<hello />
</epp>

または:

<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<hello></hello>
</epp>

できれば XSD を変更したり、XJC コンパイル済みクラスを手動で変更したりせずに、これを可能にする方法はありますか?

4

2 に答える 2

4

問題は次のとおりです。スキーマは element の型を定義していませんhello。その結果、XJC は type のフィールドを生成しますObject。つまり、JAXB は、マーシャリング中に、扱っているオブジェクトの種類を検出する必要があります。詳細は定かではありませんが、ランタイムの型をチェックして対応してくれるのではないかと思います。String実際にフィールドに入力したものであるためhello、スキーマタイプ(つまりxs:string)に直接バインドされているため、JAXBはそれに対応します。ここまでは順調ですね。

しかし、JAXB はアンマーシャリングにも役立つ XML を生成しようとしています。スキーマは型を指定しておらず、helloフィールドはオブジェクトであるため、XML から非整列化しようとすると、実際にコンテンツを何に変換するかについて JAXB が推測することになります。その方法を伝える 1 つの方法は、xsi:type属性を使用して XML 要素で型を指定することです。この属性はxsi-bound 名前空間に含まれるため、プレフィックスを宣言してバインドする必要があります。それが で起こることxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"です。しかし、それだけではありません...宣言されxsi:typeたものは、プレフィックスにバインドされた XML スキーマ名前空間の型を使用します。つまり、xsそれも宣言する必要があります! したがって、xmlns:xs="http://www.w3.org/2001/XMLSchema".

その結果、XML を使用する人に、XML に実際に文字列が含まれていることを伝えるための名前空間宣言の混乱が生じます。これは、スキーマの hello 要素の型として文字列を追加することで解決できますが、それは選択肢ではありません。

幸いなことに、あなたは完全に運が悪いわけではありません。外部バインディング ファイルを使用してバインディングをカスタマイズできます。詳細はこちら: http://download.oracle.com/docs/cd/E17802_01/webservices/webservices/docs/2.0/tutorial/doc/JAXBUsing4.html

通常、このバインディング ファイルでうまくいくはずです。

<?xml version="1.0" encoding="UTF-8"?>
<bindings xmlns="http://java.sun.com/xml/ns/jaxb" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/jaxb http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd"
    version="2.1">

    <!-- Bindings for the general schema -->
    <bindings schemaLocation="test.xsd" node="/xs:schema">

        <bindings node="xs:element[@name='epp']">
            <bindings node=".//xs:element[@name='hello']">
                <javaType name="java.lang.String" />
            </bindings>
        </bindings>

    </bindings>

</bindings>

...しかし、これで xjc を試すと、エラーが発生しますthe compiler was unable to honor this javaType customization。スキーマの hello 要素に標準のスキーマ型 (string や int など) を指定すると機能しますが、実際に変換用の parse メソッドと print メソッドを提供しようとすると機能しませんでした。これは、スキーマでタイプが指定されていない場合に発生する xjc のバグであると想定します。

他の誰かがバインディングの問題についてアドバイスをくれることを願っています。それ以外の場合、私が目にする唯一のオプションは、XJC を解き放ち、型指定されていないすべての要素をデフォルトで文字列に設定する前に、XSLT 変換を介してスキーマを送信することです。

于 2011-10-28T14:35:59.250 に答える
1

スキーマで要素の型が指定されていない場合、既定の型は ですxs:anyType。これは、XML スキーマ型階層のルートです (すべての単純型と複合型は のサブタイプですanyType)。

JAXB がanyType要素に遭遇すると、それを type のプロパティにバインドしますObject。このプロパティに入れる値は、

  • null、要素を省略することを意味します
  • JAXBContext が認識しているタイプのオブジェクト。これは通常の方法でマーシャリングされxsi:type、元のタイプが何であったかを示すために追加されます。
  • 使用するorg.w3c.dom.Element実際の XML を表す です。

だからこれを試してください:

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
Document doc = dbf.newDocumentBuilder().newDocument();

epp.setHello(doc.createElementNS("urn:ietf:params:xml:ns:epp-1.0", "hello"));
于 2012-12-31T16:54:24.007 に答える