2011-11-04 2 views
7

J'ai un élément défini comme xsd: double. Si j'essaie de placer une valeur, disons 285 dans l'élément et que je la rassemble, j'obtiens une sortie de 285.0 ... C'est bien. Cependant, si je mets une valeur de 285292746 par exemple, j'obtiens une sortie de 2.85292746E8 quand Je marshal. J'aime quelque chose pour que la sortie double ne soit pas convertie en notation scientifique avec décimal? Fondamentalement je veux 285292746 ou 2852292746.0000000Jaxb: conversion de type double de liaison globale à l'aide de XMLAdapter

java.lang.Double.toString() utilise "la notation scientifique informatisée" pour certaines valeurs qui produisent des isues pour xml.

Je sais que la double représentation de la valeur donnée est correcte. Mais le fait que la valeur soit au format exponentiel, Le système sur lequel je travaille accepte mon XML mais ne sait pas quoi faire avec la valeur exponentielle et cela empêche mon programme de fonctionner correctement. Changer xsd: double type en WSDL ou serveur n'est pas faisable pour moi. Je travaille côté client.

Je suis tombé sur Jaxb: liaison pour xsd: type double. J'ai encore du mal à résoudre le problème pour envoyer des valeurs à double valeur dans un format non-expéditeur.

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

} 

J'ai besoin d'aide pour utiliser DoubleSerializer afin de pouvoir transmettre des valeurs sans exposant. J'ai essayé d'utiliser xmlAdapter Annotation dans ma classe MyLogClient.java. J'ai besoin de savoir comment je peux résoudre cette situation.

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: déclaration de type est ci-dessous: -

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

sortie pour le champ d'identification est: -

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

Répondre

1

La meilleure façon peut-être d'utiliser un liaison personnalisée (clause javaType) avec votre compilateur JAXB. La documentation peut être trouvée here. Selon si vous devez marshaler et unmarshall double, la solution pourrait être aussi simple que de remplacer le mapping par quelque chose comme un BigDecimal au niveau global (sachant que bien que les doubles et les décimales soient des choses totalement différentes, vous semblez vouloir une décimale représentation), ou pour utiliser un convertisseur de type de données (le lien ci-dessus vous donne des exemples pour toutes ces options).

+0

Pourriez-vous donner des exemples spécifiques? Pensez-vous que l'option de l'adaptateur xml est bien. J'ai essayé d'utiliser comme indiqué ci-dessus dans mon exemple JAxDouble Serialzer mais je ne sais pas ce que je manque. – user1029083

7

Vous pouvez utiliser un fichier des liaisons externes comme ce qui suit:

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> 

racine.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 Appel

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

Racine

La classe générée pour le type de racine aura XmlAdapter cours inscrits sur les propriétés 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

Le XmlAdapter utilise les méthodes que vous avez configuré dans le fichier 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

Merci beaucoup. Je vais essayer de cette façon. Je n'ai pas de fichier xsd mais le code source est généré à partir du fichier wsdl ce fichier est publié via l'URL. Je suppose que je devrais utiliser wsimport ou quelque chose à faire avec wsdl. xjc -d out -b binding.xml (http: //localhost/MyClient.wsdl) ou wsimport -d out -b binding.xml location.wsdl. – user1029083

Questions connexes