2012-09-14 16 views
7

私はXStreamのを使用していると私は、XMLのサンプルを持っていますので、アイデアがマップすることであるXMLマッピング属性

<person> 
    <firstname>Joe</firstname> 
    <lastname>Walnes</lastname> 
    <phone value="1234-456" /> 
    <fax value="9999-999" /> 
</person> 

と私はクラスに

public class Person { 

    private String firstname; 
    private String lastname; 
    private String phone; 
    private String fax; 

} 

それをマッピングするためにwhantネストされた要素の属性を現在のオブジェクトに追加します。 私はすぐに使えるコンバータを見つけようとしましたが、成功しませんでした。私は新しいコンバータを実装することによってそれが可能だと信じているが、誰かがすでにこれをしている可能性があります。それとも私が見つけられなかった解決策があります。

更新:私が実装しようとしている

アイデアが作成され、マッピングされているの不要なエンティティを省略しています。 Phone and Faxエンティティはまったく必要ありません。私のモデルにはその属性だけが必要です。私が解析しようとしているXMLスキーマは、私のための第三者であり、変更することはできません。

+0

まあマダラ!私はこれを修正しました。ちょうどゼロから書かれた。 –

+0

あなたは何を探しているのかを明確にすることができますか? "私は電話とファックスのエンティティは必要ありません"と言っていますが、あなたはそれらを持っていません。あなたのモデルの文字列であり、別のエンティティではありません。四つすべて? – JoeG

+0

問題は、XMLサンプルをモデルにマップする方法です。余計な労力を要せずに、XStreamは、たとえ明示的に省略されていても、XML要素がモデルメンバーとして解釈されると考えていました。リッチなXMLスキーマを持つことで、意味のあるデータの重複した「所有者」を逃れるためにモデルを単純化したいと思うでしょう。暗黙のコレクションは良好ですが、十分ではありません。 –

答えて

5

私はそれを行いますすぐに使用できるコンバータを知りませんが、それはあなたが注釈

を使用して関連分野へのコンバータを添付することができます1

import com.thoughtworks.xstream.converters.*; 
import com.thoughtworks.xstream.io.*; 

public class ValueAttributeConverter implements Converter { 
    public boolean canConvert(Class cls) { 
    return (cls == String.class); 
    } 

    public void marshal(Object source, HierarchicalStreamWriter w, MarshallingContext ctx) { 
    w.addAttribute("value", (String)source); 
    } 

    public Object unmarshal(HierarchicalStreamReader r, UnmarshallingContext ctx) { 
    return r.getAttribute("value"); 
    } 
} 

を書くために非常に簡単です​​

この作品を作るために、あなたがする必要があるすべての注釈を読むためにXStreamのを指示している。

XStream xs = new XStream(); 
xs.processAnnotations(Person.class); 
Person p = (Person)xs.fromXML(
    "<person>\n" + 
    " <firstname>Joe</firstname>\n" + 
    " <lastname>Walnes</lastname>\n" + 
    " <phone value='1234-456' />\n" + 
    " <fax value='9999-999' />\n" + 
    "</person>"); 
System.out.println(p); 
// prints fn: Joe, ln: Walnes, p: 1234-456, f: 9999-999 
+0

ありがとう、私はそれをチェックします。私はそれがどのように動作するのか分かりません。おそらく理解コンバータの不足のために。 –

+1

XStreamがBean型クラスを表すXMLを読み込んでいるとき、要素名を読み込んで処理するフィールドを調べ、関連するコンバータに委譲します。コンバーターの 'unmarshal'メソッドには、(この場合)' phone'要素の開始タグを指し示す 'HierarchicalStreamReader'が渡されます。通常の単一値コンバータは要素のテキスト内容で動作しますが、カスタムコンバータは代わりに 'value'という名前の属性を参照します。要素名が何であるかは気にする必要はありません。 –

0

XStreamエイリアスのチュートリアルの「属性のエイリアシング」セクション:http://x-stream.github.io/alias-tutorial.htmlを参照してください。

+0

オラフありがとうございます。私は質問を更新しました。それはチュートリアルのシナリオで達成できますか、私は疑問に思っていますか? –

4

注:私はEclipseLink JAXB (MOXy)の先導者であり、JAXB (JSR-222)専門家グループのメンバーです。

XStream以外のライブラリを使用している場合、@XmlPath拡張子を利用する方法はEclipseLink JAXB(MOXy)です。

@XmlPath注釈が(参照:http://blog.bdoughan.com/2010/07/xpath-based-mapping.html)あなたは、XPathでXMLドキュメント内の場所へのあなたのフィールド/プロパティをマッピングすることができます。

package forum12425401; 

import javax.xml.bind.annotation.*; 
import org.eclipse.persistence.oxm.annotations.XmlPath; 

@XmlRootElement 
@XmlAccessorType(XmlAccessType.FIELD) 
public class Person { 

    private String firstname; 
    private String lastname; 

    @XmlPath("phone/@value") 
    private String phone; 

    @XmlPath("fax/@value") 
    private String fax; 

} 

jaxb.properties

あなたのJAXBプロバイダとしてMOXYを指定するには、あなたが(:http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.htmlを参照してください):次のエントリを持つドメインモデルと同じパッケージにjaxb.propertiesというファイルをインクルードする必要があり

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory 

デモ

以下のコードは、XMLをドメインモデルに変換し、ドメインモデルをXMLに書き戻します。

package forum12425401; 

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

public class Demo { 

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

     Unmarshaller unmarshaller = jc.createUnmarshaller(); 
     File xml = new File("src/forum12425401/input.xml"); 
     Person person = (Person) unmarshaller.unmarshal(xml); 

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

} 

input.xmlに/出力

<?xml version="1.0" encoding="UTF-8"?> 
<person> 
    <firstname>Joe</firstname> 
    <lastname>Walnes</lastname> 
    <phone value="1234-456"/> 
    <fax value="9999-999"/> 
</person> 
+0

このような詳細な回答をいただきありがとうございます。私はJAXBがこの問題を調査したことを発見しました。@ XmlPathが私が最初に気がついたことでした。あなたはそれがうまくいくかについて簡単に説明してください、私はそれが引き抜かれるために追加の要素を必要としていることを意味しますか?パフォーマンスとデータの効率性は今私にとって最強の要件です。 –

+1

@ViktorStolbin - '@XmlPath'は実際にはJAXB(JSR-222)仕様のEclipseLink MOXy実装で提供される拡張機能です。 MOXyは、XML文書の単一パス深さの最初のトラバーサル中に処理できるXPathのサブセットをサポートしています。これは非常に効率的なプロセスです。 –