マーシャリングされた要素/タグで不要な名前空間宣言を避ける方法は?

How to avoid unnecessary namespace declarations in a marshalled element/tag?


質問 written by skaffman @2011-10-28 16:27:52Z

: 6 : 2 : 4

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

XJC 2.2とJAXB 2.2を使用して、シンプルバインディングモードを使用して、空のhello要素内にルート要素を作成したい。 しかし、マーシャリングされると、多くの余分な名前空間がらくたを受け取ります。 私にはそれは不必要に見えます。 (それでも動作しますが、ectを送信するためのデータが増えます...)

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コンパイル済みクラスを手動で変更しますか?

コメント 1

質問のタイトルを編集する場合はどうですか?あなたはコンテンツなしで要素を生成する方法を尋ねているように感じますが、それは世話をします。本当の目標は、余分な名前空間宣言を避けることです。

written by -G_H @2011-10-28 13:47:25Z

コメント 2

問題ありません、ここでの最初の質問です... :)、はい、目標はこれらの名前空間decsを取り除くことです-Phoenix

written by the II @2011-10-28 13:49:35Z

コメント 3

Hello値を設定しない(epp.setHello( "")を実行しない)ことを試みましたか?

written by セバスチャンチャスカヴィエツ @2011-10-28 14:02:07Z

コメント 4

はい。ただし、空のルート要素のみが作成されます。hello要素は必要ないため。ルート要素には、これらの要素の少なくとも1つが必要です。必要に応じてhelloを設定しようとしましたが、コマンド要素があっても常に表示されます。したがって、結果は、相手からの無効なxsd検証です。

written by フェニックスII II @2011-10-28 14:28:00Z

回答 1 written by G_H @2011-10-28 14:35:59Z
4

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

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

その結果、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要素で標準のスキーマタイプ(文字列やintなど)を指定すると機能しますが、実際に変換用の解析メソッドと出力メソッドを提供しようとしたときに機能しませんでしたので、これがxjcのバグであり、スキーマでタイプが指定されていない場合に発生すると仮定します。

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

コメント 1

これを試しましたが、残念ながら同じエラーが発生します... epp.setHello("");を使用している間にマーシャラーに要素を出力する必要があることを知らせます。文字列を生成しないhello要素を設定する別の方法があるかもしれません。XJCは関数をpublic void setHello(Object value) nullを使用してコンパイルするので、nullを設定しないのと同じであり、マーシャラーによって取得されません。「愚かな」推測をするために、JAXBの「null」オブジェクトはありますか?:)

written by フェニックスII @2011-10-28 15:34:27Z

コメント 2

@PhoenixtheIIバインディングファイルを使用しましたか?もしそうなら、それは機能しましたか?私はJDK 7で配布されたXJCを使用しているので、以前のバージョンがこれで動作する可能性があります。空の文字列を設定してhello要素を「強制」したいのは知っています 、それ正しいアプローチです。nullを設定すると、省略されます。しかし、ここでの目標は、 Eppクラスのhelloフィールドを何らかの具象型に変えることです。これは、 Objectあることがxsi:type fluffをすべて追加する原因になるためです。

written by G_H @2011-10-28 15:48:48Z

コメント 3

ああ、私は最初にパーティーxsdに変更を加えてJAXBと互換性のあるもの(@XmlRootElementが欠落している;))であるため、「ねじ込み」モードを実行することにしました。そして、あなたが言ったように:私は、hello要素が文字列型であることを伝えるためにxsdを変更しました。<element name="hello" type="string"/>ありながら同じJavaコードを使用すると、望ましい結果が得られます。これで、私のXSDがこれらのhelloの受信と互換性があることを望みますが、それをテストする必要があります

written by Phoenix II II @2011-10-28 15:52:57Z

コメント 4

@GHのコメント:ダウンロードしたJAXB実装2.2.4u1を使用しています。バンドルされたJDK6の古いもの(2.1.10)ではなく、これをコンパイルするために使用するコマンド: ../../../../../../lib/jaxb-2.2.4u1/jaxb-ri-20110601/bin/xjc.sh epp-1.0.xsd -episode epp-1.0.episode -b eppcom-1.0.episode -extension ../xjcExtensions.xml -catalog epp.cat -p com.somelocation.xyzepp1 -d ../../../../../ lib/jaxb-2.2.4u1/jaxb- ../../../../../../lib/jaxb-2.2.4u1/jaxb-ri-20110601/bin/xjc.sh epp-1.0.xsd -episode epp-1.0.episode -b eppcom-1.0.episode -extension ../xjcExtensions.xml -catalog epp.cat -p com.somelocation.xyzepp1 -d ../../../../../ここで、xjcExtensions.xmlには、説明した追加のバインディング情報と「globalBindings <xjc:simple />」があります

written by Phoenix II II @2011-10-28 15:59:10Z

コメント 5

文字列として何かを宣言すると問題が発生する場合、私は驚かれることでしょう。とにかくこれがデフォルトだと思っていましたが、確認やXML Schemaによると要素のデフォルトのタイプは実際に見つけるのに苦労しています。とにかく、手動でスキーマを変更することが実行可能な場合(たとえば、毎日のビルドでこれらの100の要素宣言が好きではない場合)、トリックを行います。そして、それがなくても、少なくともXMLは整形式で有効です。いくつかの余分なバイトが傷つくことはありませんが、いかもしれません。@XmlSeeAlsoにmmyselfの「ありがとう」という名前空間の冗長な問題が発生しました。

written by G_H @2011-10-28 15:59:39Z

回答 2 written by Ian Roberts @2012-12-31 16:54:24Z
1

スキーマが要素のタイプを指定しない場合、デフォルトのタイプはxs:anyTypeであり、これはXMLスキーマタイプ階層のルートです(単純および複合タイプはすべてanyTypeサブタイプです)。

JAXBはanyType要素を検出すると、 Object型のプロパティにバインドします。 このプロパティに入れる値は

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

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

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"));