2016-09-16 6 views
2

xml文字列にマーシャリングしようとしているXMLGregorianCalendarオブジェクトがあります。私は別のXMLオブジェクトをアンマーシャリングすることによってこのオブジェクトを受け取りました。どちらも "dateTime"タイプなので、まったく同じである必要があります。JAXB時刻を指定しないと空白になる時刻

まだ、私がマーシャリングすると、xmlに空白が表示されます。

この問題を説明するために、私は裸の骨まですべてを取り除き、一般化しましたin this example here。 2つのJavaファイル、コピー、貼り付け、そのまま実行残念ながら、それは返し、

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<TheObject> 
    <DOB>2016-09-16</DOB> 
</TheObject> 

:しかし

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<TheObject> 
    <DOB></DOB> 
</TheObject> 

注:ペーストビンの例では、私はその場でたXMLGregorianCalendarを作成するのではなく1をつかむあなた受けるべき出力は以下のようになります下のコードのような別のオブジェクトから、技術的には同じものではありませんが、私は最終的に同じ問題を正確に示していると思います...

私の特定の問題にDDよりコンテキスト:これはバグのいくつかの種類である:

//Here are the objects themselves (names changed to protect the innocent) 
//complete with annotations... 
public class Object1{ 
    ... 
    @XmlElement(name = "DOB") 
    @XmlSchemaType(name = "dateTime") 
    protected XMLGregorianCalendar dob; 
    ... 
} 

public class Object2{ 
    ... 
    @XmlElement(name = "DOB") 
    @XmlSchemaType(name = "dateTime") 
    protected XMLGregorianCalendar dob; 
    ... 
} 

//and here's the snippet where the date object(date of birth) gets set 
//from one object to another. 
object2.setDOB(object1.getDOB()); 

//and finally, marshalling it to an xml string 
private String marshallTheObject(Object2 theObject) throws JAXBException{ 
    JAXBContext jaxbContext = JAXBContext.newInstance(Object2.class); 
    Marshaller jaxbMarshaller = jaxbContext.createMarshaller(); 
    jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
    StringWriter sw = new StringWriter(); 
    jaxbMarshaller.marshal(object2, sw); 
    String output = sw.toString(); 
    return output; 
} 

//the xml output shows: <DOB></DOB> instead of the date 

は私が8をJavaのJAXBのバージョンを使用していますが

だから私の質問をされています...がバンドルされていますか?もしそうでなければ、私は何が間違っているのですか?生成されたJavaコードを変更することなくこの問題を回避するにはどうすればよいですか?私は...

編集をどちらか、それを生成するために使用されるXSDファイルを編集することはできません。参考のために、XSDファイルとしてDOBを示しています

<xs:element name="DOB" type="xs:dateTime" /> 
+0

エキスパートが必要ではないかもしれませんが、XSDも投稿します。 –

+0

xsdファイルから関連するスニペットを追加しました。ペーストビンの例では、複雑さの問題は完全には解消されていません。 – Hylianux

答えて

2

xsdファイルを直接変更することはできませんでしたが、私は気づいていなかったことは、クラス自身がバインディングファイルを通じて生成された方法を変更できることでした。この場合はmavenを使用していないため、解決策を決定するのは少し難しかったです。私はxsdファイルからjaxbクラスを生成するeclipseに組み込まれた機能を使ってクラスを生成していました。あなたが指定して取得 -

私は、バインディングについての詳細は、私はそのファイルがMavenのに対して、中に配置する必要が場所を正確にわからないんだけど、それを、それは問題ではありません日食の方法を行う際にhere

ファイルを学びましたここで、バインディングファイルはjaxbクラス生成ウィザードの実行中です。

生成したら、独自のxmlアダプターをコーディングする必要があります。

import java.text.ParseException; 
import java.text.SimpleDateFormat; 
import java.util.Date; 

import javax.xml.bind.annotation.adapters.XmlAdapter; 

public class CalendarDateTimeAdapter extends XmlAdapter<String, Date> { 

    //Sadly my specific situation requires me to strip the time off of all dateTime objects 
    //It's bad, but I didn't get to design the system, so this is the best compromise... 
    private final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); 

    @Override public Date unmarshal(String value) throws ParseException { 
     synchronized (sdf){ 
      return sdf.parse(value); 
     } 
    } 

    @Override public String marshal(Date value) { 
     if(value == null) { return null; } 
     synchronized(sdf){ 
      return sdf.format(value); 
     } 
    } 
} 

あなたのマーシャリングを行っているときに...

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE jaxb:bindings> 

<jaxb:bindings version="2.1" 
    xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"> 

    <!-- Prevent wrapping data types into JAXBElements. --> 
    <jaxb:globalBindings generateElementProperty="false"> 

     <!-- Use java.util.Date instead of XMLGregorianCalendar. --> 
     <xjc:javaType name="java.util.Date" xmlType="xs:dateTime" 
      adapter="com.package.location.adapter.CalendarDateTimeAdapter"/> 
     <xjc:javaType name="java.util.Date" xmlType="xs:date" 
      adapter="com.package.location.adapter.CalendarDateAdapter"/> 
     <xjc:javaType name="java.util.Date" xmlType="xs:time" 
      adapter="com.package.location.adapter.CalendarTimeAdapter"/> 

    </jaxb:globalBindings> 
</jaxb:bindings> 

をあなたのクラスは、あなたのバインディングファイルで指定されたものと一致していることを確認し、それを使用するsetAdapter関数を使用します。

private String marshallObject(MyObject myObject) throws JAXBException{ 
    JAXBContext jaxbContext = JAXBContext.newInstance(MyObject.class); 
    Marshaller jaxbMarshaller = jaxbContext.createMarshaller(); 
    jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
    jaxbMarshaller.setAdapter(new CalendarDateTimeAdapter()); 
    StringWriter sw = new StringWriter(); 
    jaxbMarshaller.marshal(myObject, sw); 
    String output = sw.toString(); 
    return output; 
} 

これで、XMLGregorianCalendarオブジェクトではなくDateオブジェクトに解決されます。そして、明らかに、DateオブジェクトはXMLGregorianCalendarsよりもうまく動作します...

私はまだ取り込まれた非整列のxmlが同じxmlになるようマーシャリングされていませんが、これはまさに私ですそれがすべて働き始めるようにしました。私はここで大会に反対する何かをしたと確信しています、もし私が持っているなら、私に知らせてください。

もう一度、私はMavenやフレームワーク(SpringMVCなど)を使用していないことを読者に思い出させます。

1

JAXBを使用して、時間を設定していることを好きではありません。 dateTimeの場合はDatatypeConstants.FIELD_UNDEFINEDになります。あなたがその行をコメントアウトした場合:ようdateTimeにから日付を変更する

<DOB>2016-09-16T00:00:00.000</DOB> 

たり、生成された注釈を変更することができます(または使用してカスタマイズバインディング):

// calendar.setTime(DatatypeConstants.FIELD_UNDEFINED, DatatypeConstants.FIELD_UNDEFINED, DatatypeConstants.FIELD_UNDEFINED); 

はそれはのようなものをマーシャリングします:

@XmlSchemaType(name = "date") 
protected XMLGregorianCalendar dob; 

<DOB>2016-09-16</DOB> 

さらに深く移動したい場合は、thisのようなものが出発点になるかもしれません。

+0

このXMLGregorianCalendarは、dateTimeであると指定された別のオブジェクトをアンマーシャリングしていません。ユーザーは日付だけを入力したので、最終的にはペーストビンのものとよく似たカレンダーを非整列化しました。日時を日付時刻に非マーシャルできますが、元に戻すことはできません。とにかく、最後にタイムスタンプを持つことは、ユーザーが望むものではありません。あなたが送ったリンクを調べたところ、その機能を可能にするために生成されたjavaを変更する必要があるように見えます。私はxjbファイルを使用することができましたが、それはメイバライズされていないので、どこに行くのか分かりません。 – Hylianux

+0

Mavenの統合例[here](http://www.mojohaus.org/jaxb2-maven-plugin/Documentation/v2.2/example_xjc_basic.html)と[ここ](https://github.com)が見つかります/ highsource/maven-jaxb2-plugin)。 –

関連する問題