2011-11-04 12 views
7

Tengo un elemento definido como xsd: double. Si trato de colocar un valor como 285 en el elemento y luego lo obtengo obtengo un resultado de 285.0 ... Eso está bien. Sin embargo, si pongo un valor de, por ejemplo, 285292746, obtengo una salida de 2.85292746E8 cuando Yo mariscal. Me gusta algo para que la doble salida no se convierta en notación científica con decimal? Básicamente quiero 285292746 o 2852292746.0000000Jaxb: vinculación global Conversión de tipo doble con XMLAdapter

java.lang.Double.toString() utiliza la "notación científica computarizada" para ciertos valores que producen isues para xml.

Sé que la representación doble del valor dado está bien. Pero el hecho de que el valor estaba en formato exponencial. El sistema en el que estoy trabajando es aceptar mi XML pero no sé qué hacer con el valor exponencial y eso hace que mi programa no funcione correctamente. Cambiar xsd: double type en WSDL o servidor no es factible para mí. Estoy trabajando en el lado del cliente.

Me encontré con Jaxb: vinculante para xsd: tipo doble. Todavía estoy teniendo dificultades para solucionar el problema para enviar valores de doble valor en formato no-exponentes.

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

} 

Necesito ayuda cómo utilizar DoubleSerializer para que pueda pasar valores sin exponentes. Intenté usar xmlAdapter Annotation en mi clase MyLogClient.java. Necesito saber cómo puedo resolver esta situación.

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: declaración de tipo es el siguiente: -

<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> 

de salida para el campo identificador es: -

 <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> 

Respuesta

1

La mejor manera podría ser utilizar una enlace personalizado (cláusula javaType) con su compilador JAXB. La documentación se puede encontrar here. Dependiendo de si tiene que ordenar y deshacer dobles, la solución podría ser tan simple como anular la asignación a algo como un BigDecimal a nivel global (entendiendo que aunque los dobles y los decimales son cosas totalmente diferentes, parece que quiere un decimal representación), o para usar un convertidor de tipo de datos (el enlace de arriba le da ejemplos para todas estas opciones).

+0

¿Podría dar algunos ejemplos específicos? ¿Creerías que la opción del adaptador xml está bien? Traté de usarlo como se muestra arriba en mi ejemplo JAxDouble Serialzer, pero no estoy seguro de lo que me falta. – user1029083

7

usted podría utilizar presentar una fijaciones externas como la siguiente:

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> 

raíz.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 llamada

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

Raíz

La clase generada para el tipo raíz tendrán XmlAdapter clases registrados en las propiedades de dos plazas:

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

El XmlAdapter utiliza los métodos que ha configurado en el archivo 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)); 
    } 

} 
+0

Muchas gracias. Voy a intentarlo de esta manera. No tengo el archivo xsd, pero el código fuente se genera a partir del archivo wsdl y el archivo se publica a través de la URL. Supongo que tendré que usar wsimport o algo para enlazar con wsdl. xjc -d out -b binding.xml (http: //localhost/MyClient.wsdl) o wsimport -d out -b binding.xml location.wsdl. – user1029083

Cuestiones relacionadas