Jaxb: глобальное связывание Двойное преобразование типов с использованием XMLAdapter - PullRequest
8 голосов
/ 04 ноября 2011

У меня есть элемент, определенный как xsd: double. Если я пытаюсь поместить значение, скажем, 285, в элемент, а затем упорядочить его, я получаю вывод, равный 285,0 ... Это нормально. Однако, если я добавлю значение, скажем, 285292746, я получу вывод, равный 2,85292746E8, когда Я маршал. Мне нравится то, что двойной вывод не преобразуется в научную запись с десятичной? В основном я хочу 285292746 или 2852292746.0000000

java.lang.Double.toString () использует «компьютеризированную научную нотацию» для определенных значений, которые создают isues для xml.

Я знаю, что двойное представление заданного значения в порядке. Но факт, что значение было в экспоненциальном формате, система, над которой я работаю, принимает мой XML, но не знает, что делать с экспоненциальным значением, и это заставляет мою программу работать неправильно. Изменение типа xsd: double в WSDL или на сервере для меня нецелесообразно. Я работаю на стороне клиента.

Я сталкивался с Jaxb: привязка для типа xsd: double. У меня все еще есть трудное время, чтобы решить проблему, чтобы отправить значение типа double в неэкспонентном формате.

package com.logger.client 
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.bind.DatatypeConverter;

public class JaxbDoubleSerializer  extends XmlAdapter<String, Double>
{


    public Double unmarshal(String value) {
        return ((double)javax.xml.bind.DatatypeConverter.parseDouble(value));
    }

    public String marshal(Double value) {
        if (value == null) {
            return null;
        }
        return (javax.xml.bind.DatatypeConverter.printDouble((double)(double)value));
    }

}

Мне нужна помощь, как использовать DoubleSerializer, чтобы я мог передавать значения без показателей степени. Я попытался использовать аннотацию xmlAdapter в своем классе MyLogClient.java. Мне нужно знать, как я могу решить эту ситуацию.

package com.logger.client 
import javax.xml.ws.BindingProvider;
import javax.xml.bind.JAXBElement;import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.XmlValue;


public class MyLogClient 
{
   //Private member fields

  /** Object factory used to create user-and-role specific objects. */
    private static final ObjectFactory _of = new ObjectFactory();

     @XmlJavaTypeAdapter(JaxbDoubleSerializer.class)
   public JAXBElement<Double> msgFileId;

       @XmlJavaTypeAdapter(JaxbDoubleSerializer.class)
   public Double dNumber;


public final void createEntry;
    (
        final String userName,
        final String time,
        final String logMsgStringId,
        final Params logMsgParamsVal,
        final Integer logMessageFieldID
    )

    throws JAXBException
    {

       JAXBElement<String> username = _of.createParamsParam(userName);
      JAXBElement<String> strTime       = _of.createLogRequestTime(time);


        // Build the LogRequest request.
       final LogRequest _LogRequest = _of.createLogRequest();
       _LogRequest.setUserName(userName);
       _LogRequest.setTime(strTime);

        //Following is the main problem
        int nMsgArgs =  285292746;
       dNumber = Double.parseDouble(Integer.toString(nMsgArgs));  
      //After parsing double Value I get dNumber is now  2.85292746E8

      //MsgFile Id is of Type JAXBElement<Double>
      //CreateLogMessageIdentifier takes Double param
      //So the main problem is here..the value of double field in soap request 
      //is being sent in exponential format. I need to send as I explained above
      //285292746.

       msgFileId   = _of.createLogMessageIdentifier(dNumber); 

      JAXBElement<String> strIdVal = _of.createLogMessageFileId(logMsgStringId);

      final LogMessage logMessage = _of.createLogMessage();

     JAXBElement<Params> _logMsgParams =_of.createLogMessageParams(logMsgParamsVal);

     //Following is where I am trying to use marshall for double type.

     JAXBContext context = JAXBContext.newInstance("package com.logger.client ");
     context.createMarshaller().marshal(msgFileId, System.out);

      logMessage.setIdentifier(msgFileId);  //Method takes JAXBElement<Double>

      logMessage.setFileId(strIdVal );
      logMessage.setParams(_logMsgParams);

      JAXBElement<LogMessage> logMsgValue = _of.createLogRequestLogMessage(logMessage);


        _LogRequest.setLogMessage(logMsgValue);

        // Set the log entry
        port.log(_LogRequest); //Request is sent to server.

}

WSDL xsd: объявление типа ниже: -

  <xsd:complexType name="LogMessage">
         <xsd:sequence>
        <xsd:element name="fileId" type="xsd:string" minOccurs="0" nillable="true" />
        <xsd:element name="identifier" type="xsd:double" minOccurs="0" nillable="true" />
        <xsd:element name="params" type="tns:Params" minOccurs="0" nillable="true" />
         </xsd:sequence>
           </xsd:complexType>

Выходные данные для поля идентификатора: -

     <identifier> 2.85292746E8</indentifier> 

Whereas I want to send as. Because system does accept/recognize following types.

<identifier> 285292746</indentifier> 
or 
<identifier> 285292746.00000000</indentifier> 

Ответы [ 2 ]

8 голосов
/ 05 ноября 2011

Вы можете использовать внешний файл привязок, например:

binding.xml

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

    <jxb:globalBindings>
            <jxb:javaType name="java.lang.Double"
                xmlType="xs:double"
                parseMethod="javax.xml.bind.DatatypeConverter.parseDouble"
                printMethod="javax.xml.bind.DatatypeConverter.printDouble" />
    </jxb:globalBindings>

</jxb:bindings>

root.xsd

<?xml version="1.0"?>
<xs:schema 
    elementFormDefault="qualified"
    targetNamespace="http://www.example.com"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">

    <xs:complexType name="root">
        <xs:sequence>
            <xs:element name="foo" type="xs:double" />
            <xs:element name="bar" type="xs:double" />
        </xs:sequence>
    </xs:complexType>

</xs:schema>

Вызов XJC

xjc -d out -b binding.xml root.xsd

Root

Класс, сгенерированный для корневого типа, будет иметь XmlAdapter зарегистрированных классовв свойствах Double:

package com.example;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlSchemaType;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import org.w3._2001.xmlschema.Adapter1;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "root", propOrder = {
    "foo",
    "bar"
})
public class Root {

    @XmlElement(required = true, type = String.class)
    @XmlJavaTypeAdapter(Adapter1 .class)
    @XmlSchemaType(name = "double")
    protected Double foo;
    @XmlElement(required = true, type = String.class)
    @XmlJavaTypeAdapter(Adapter1 .class)
    @XmlSchemaType(name = "double")
    protected Double bar;

    public Double getFoo() {
        return foo;
    }

    public void setFoo(Double value) {
        this.foo = value;
    }

    public Double getBar() {
        return bar;
    }

    public void setBar(Double value) {
        this.bar = value;
    }

}

Adapter1

* XmlAdapter использует методы, настроенные вами в файле binding.xml.

package org.w3._2001.xmlschema;

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

public class Adapter1 extends XmlAdapter<String, Double> {

    public Double unmarshal(String value) {
        return (javax.xml.bind.DatatypeConverter.parseDouble(value));
    }

    public String marshal(Double value) {
        if (value == null) {
            return null;
        }
        return (javax.xml.bind.DatatypeConverter.printDouble(value));
    }

}
1 голос
/ 04 ноября 2011

Лучшим способом может быть использование настраиваемой привязки (предложение javaType) с вашим компилятором JAXB.Документация может быть найдена здесь .В зависимости от того, нужно ли вам маршалировать и демаршировать двойные числа, решение может быть таким же простым, как переопределение сопоставления с чем-то вроде BigDecimal на глобальном уровне (при том понимании, что, хотя числа с двойными и десятичными числами - это совершенно разные вещи, вам, кажется, нужно десятичное) или использовать конвертер типов данных (ссылка выше дает примеры для всех этих опций).

...