سؤال

أنا أبحث عن طريقة بسيطة للتحويل بين java.util.date و javax.xml.datatype.xmlgregoriancalendar في كلا الاتجاهين.

إليك الرمز الذي أستخدمه الآن:

import java.util.GregorianCalendar;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;

/**
 * Utility class for converting between XMLGregorianCalendar and java.util.Date
 */
public class XMLGregorianCalendarConverter {  

    /**
     * Needed to create XMLGregorianCalendar instances
     */
    private static DatatypeFactory df = null;
    static {
        try {
            df = DatatypeFactory.newInstance();
        } catch (DatatypeConfigurationException dce) {
            throw new IllegalStateException(
                "Exception while obtaining DatatypeFactory instance", dce);
        }
    }  

    /**
     * Converts a java.util.Date into an instance of XMLGregorianCalendar
     *
     * @param date Instance of java.util.Date or a null reference
     * @return XMLGregorianCalendar instance whose value is based upon the
     *  value in the date parameter. If the date parameter is null then
     *  this method will simply return null.
     */
    public static XMLGregorianCalendar asXMLGregorianCalendar(java.util.Date date) {
        if (date == null) {
            return null;
        } else {
            GregorianCalendar gc = new GregorianCalendar();
            gc.setTimeInMillis(date.getTime());
            return df.newXMLGregorianCalendar(gc);
        }
    }

    /**
     * Converts an XMLGregorianCalendar to an instance of java.util.Date
     *
     * @param xgc Instance of XMLGregorianCalendar or a null reference
     * @return java.util.Date instance whose value is based upon the
     *  value in the xgc parameter. If the xgc parameter is null then
     *  this method will simply return null.
     */
    public static java.util.Date asDate(XMLGregorianCalendar xgc) {
        if (xgc == null) {
            return null;
        } else {
            return xgc.toGregorianCalendar().getTime();
        }
    }
}

هل هناك أي شيء أكثر بساطة ، مثل بعض مكالمات API التي أغفلتها؟

يبدو التحويل بين تاريخ/وقت XML القياسي وكائن تاريخ Java بمثابة مهمة روتينية جميلة وأنا مندهش من أنني يجب أن أكتب هذا الرمز على الإطلاق.

أي اقتراحات؟

ملحوظات:يتم تدوين فصول jaxb الخاصة بي من مخطط. لا تسمح لي عملية الإنشاء في مشروعي بإجراء تغييرات يدوية على الفصول التي تم إنشاؤها. يتم إنشاء عناصر XS: DateTime بواسطة XJC كـ XMLGregorianCalendar في فئات JaxB. يتم تمديد المخطط ويتم تعديله بشكل دوري ، لذلك يُسمح لي بإجراء تغييرات محدودة على ملف Schema XSD.

تحديث على الحل: سمح لي الحل الذي اقترحه بليز بإخراج XMLGregorianCalendar من المزيج والتعامل مع كائنات java.util.calendar بدلاً من ذلك. عن طريق إضافة جملة ربط JaxB في الجزء العلوي من ملف المخطط الخاص بي ، فإن XJC قادرة على إنشاء تعيينات أكثر ملاءمة لـ XS: DateTime في فئات JaxB الخاصة بي. فيما يلي بعض المقتطفات التي تظهر التعديلات في ملف XSD الخاص بي.

عنصر الجذر في ملف XSD:

<xs:schema xmlns:mydata="http://my.example.com/mydata" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" targetNamespace="http://my.example.com/mydata" elementFormDefault="unqualified" attributeFormDefault="unqualified" version="0.2" xml:lang="en" jaxb:version="2.0">

كتلة التعليق التوضيحي JaxB ، تم إدخالها مباشرة بعد عنصر الجذر في XSD:

<xs:annotation>
    <xs:appinfo>
        <jaxb:globalBindings>
            <jaxb:javaType name="java.util.Calendar" xmlType="xs:dateTime" parseMethod="javax.xml.bind.DatatypeConverter.parseDateTime" printMethod="javax.xml.bind.DatatypeConverter.printDateTime" />
        </jaxb:globalBindings>
    </xs:appinfo>
</xs:annotation>

نظرًا لأن حقل XML XS: DateTime يخزن أيضًا المنطقة الزمنية ، فقد يكون من الأفضل بالنسبة لي العمل مع التقويم بدلاً من التاريخ على أي حال نظرًا لأن كائنات التقويم لديها واجهة برمجة تطبيقات جيدة للعمل مع المناطق والمناطق الزمنية. في أي حال ، أنا أكثر سعادة للتعامل مع كائنات التقويم بدلاً من xmlgregoriancalendar. لا حاجة لطرق التحويل التي أدرجتها أعلاه بعد الآن. لم أتمكن من الوصول إلى java.util.date ، لكنني أغلق بما فيه الكفاية!

هل كانت مفيدة؟

المحلول

لماذا لا تستخدم ملف الربط الخارجي لإخبار XJC لإنشاء حقول java.util.date بدلاً من xmlgregoriancalendar؟

انظر أيضا كيف يمكنني خريطة XS: تاريخ java.util.date؟ مقالات

نصائح أخرى

من xmlgregoriancalendar إلى java.util.date يمكنك ببساطة القيام به:

java.util.Date dt = xmlGregorianCalendarInstance.toGregorianCalendar().getTime();  

من java.util.date إلى xmlgregoriancalendar يمكنك القيام ببساطة:

import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.datatype.DatatypeFactory;
import java.util.GregorianCalendar;
......
GregorianCalendar gcalendar = new GregorianCalendar();
gcalendar.setTime(yourDate);
XMLGregorianCalendar xmlDate = DatatypeFactory.newInstance().newXMLGregorianCalendar(gcalendar);

تم تحرير الكود بعد التعليق الأول لـ @f-puras ، عن طريق السبب في أنني ارتكب خطأ.

اضطررت إلى إجراء بعض التغييرات لجعلها تعمل ، حيث يبدو أن بعض الأشياء قد تغيرت في هذه الأثناء:

  • سوف يشكو XJC من أن محولتي لا يمتد XMLADAPTER
  • تم رسم بعض الواردات الغريبة وغير الضرورية (org.w3._2001.xmlschema)
  • يجب ألا تكون أساليب التحليل ثابتة عند تمديد xmladapter ، من الواضح

فيما يلي مثال عمل ، آمل أن يساعد هذا (أنا أستخدم Jodatime ولكن في هذه الحالة سيكون Simpledate كافياً):

import java.util.Date;
import javax.xml.bind.DatatypeConverter;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import org.joda.time.DateTime;

public class DateAdapter extends XmlAdapter<Object, Object> {
    @Override
    public Object marshal(Object dt) throws Exception {
        return new DateTime((Date) dt).toString("YYYY-MM-dd");
    }

    @Override
        public Object unmarshal(Object s) throws Exception {
        return DatatypeConverter.parseDate((String) s).getTime();
    }
}

في XSD ، تابعت المراجع الممتازة الواردة أعلاه ، لذلك قمت بتضمين شرح XML هذا:

<xsd:appinfo>
    <jaxb:schemaBindings>
        <jaxb:package name="at.mycomp.xml" />
    </jaxb:schemaBindings>
    <jaxb:globalBindings>
        <jaxb:javaType name="java.util.Date" xmlType="xsd:date"
              parseMethod="at.mycomp.xml.DateAdapter.unmarshal"
          printMethod="at.mycomp.xml.DateAdapter.marshal" />
    </jaxb:globalBindings>
</xsd:appinfo>

كان لدي هذا النوع من الصداع أيضًا. تخلصت منه ببساطة عن طريق تمثيل الحقول الزمنية كنادي طويل في Pojo. الآن توليد رمز عميل WS الخاص بي يتعامل مع كل شيء بشكل صحيح ولا مزيد من حماقة XML-to-Java. وبالطبع ، فإن التعامل مع ميليس على جانب جافا بسيط وغير مؤلم. قبلة الصخور المبدأ!

يمكنك استخدام هذا التخصيص لتغيير التعيين الافتراضي إلى java.util.date

<xsd:annotation>
<xsd:appinfo>
    <jaxb:globalBindings>
        <jaxb:javaType name="java.util.Date" xmlType="xsd:dateTime"
                 parseMethod="org.apache.cxf.xjc.runtime.DataTypeAdapter.parseDateTime"
                 printMethod="org.apache.cxf.xjc.runtime.DataTypeAdapter.printDateTime"/>
    </jaxb:globalBindings>
</xsd:appinfo>

تخصيص التقويم والتاريخ أثناء التنقل

الخطوة 1: قم بإعداد Jaxb Binding XML لخصائص مخصصة ، في هذه الحالة أعدت للتاريخ والتقويم

<jaxb:bindings version="2.1" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" 
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<jaxb:globalBindings generateElementProperty="false">
<jaxb:serializable uid="1" />
<jaxb:javaType name="java.util.Date" xmlType="xs:date"
    parseMethod="org.apache.cxf.tools.common.DataTypeAdapter.parseDate"
    printMethod="com.stech.jaxb.util.CalendarTypeConverter.printDate" />
<jaxb:javaType name="java.util.Calendar" xmlType="xs:dateTime"
    parseMethod="javax.xml.bind.DatatypeConverter.parseDateTime"
    printMethod="com.stech.jaxb.util.CalendarTypeConverter.printCalendar" />


setp 2: أضف ملف ربط jaxb مخصص إلى Apache أو أي مكونات إضافية ذات صلة في خيار XSD كما هو مذكور أدناه

<xsdOption>
  <xsd>${project.basedir}/src/main/resources/tutorial/xsd/yourxsdfile.xsd</xsd>
  <packagename>com.tutorial.xml.packagename</packagename>
  <bindingFile>${project.basedir}/src/main/resources/xsd/jaxbbindings.xml</bindingFile>
</xsdOption>

setp 3: اكتب رمز فئة CalendarConverter

package com.stech.jaxb.util;

import java.text.SimpleDateFormat;

/**
 * To convert the calendar to JaxB customer format.
 * 
 */

public final class CalendarTypeConverter {

    /**
     * Calendar to custom format print to XML.
     * 
     * @param val
     * @return
     */
    public static String printCalendar(java.util.Calendar val) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss");
        return simpleDateFormat.format(val.getTime());
    }

    /**
     * Date to custom format print to XML.
     * 
     * @param val
     * @return
     */
    public static String printDate(java.util.Date val) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        return simpleDateFormat.format(val);
    }
}

setp 4: الإخراج

  <xmlHeader>
   <creationTime>2014-09-25T07:23:05</creationTime> Calendar class formatted

   <fileDate>2014-09-25</fileDate> - Date class formatted
</xmlHeader>
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top