2011-11-04 9 views
7

Mam element zdefiniowany jako xsd: double. Jeśli spróbuję umieścić wartość 285 w tym elemencie, a następnie ją sforam, otrzymam wynik 285.0 ... To jest w porządku .Jeśli jednak podam wartość powiedzmy 285292746, otrzymam wynik 2,85292746E8, gdy I marszałka. Podoba mi się coś, aby podwójne wyjście nie zostało przekształcone w notację naukową z dziesiętną? Zasadniczo chcę 285292746 lub 2852292746.0000000Jaxb: globalna konwergencja podwójnego wiązania za pomocą XMLAdapter

java.lang.Double.toString() używa "skomputeryzowanej notacji naukowej" dla niektórych wartości, które produkują isues dla xml.

Wiem, że podwójne przedstawienie danej wartości jest w porządku. Ale fakt, że wartość była w formacie wykładniczym. System, nad którym pracuję, akceptuje mój XML, ale nie wie, co zrobić z wykładniczą wartością i to powoduje, że mój program nie działa poprawnie. Zmiana xsd: double type w WSDL lub serwerze nie jest dla mnie wykonalna. Pracuję po stronie klienta.

Natknąłem się na Jaxb: wiązanie dla xsd: podwójny typ. Nadal mam trudności z naprawieniem problemu, aby przesłać wartości podwójnej wartości w formacie innym niż wyliczenia.

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

} 

Potrzebuję pomocy, jak korzystać z DoubleSerializer, aby móc przekazywać wartości bez wykładników. Próbowałem użyć adnotacji xmlAdapter w mojej klasie MyLogClient.java. Muszę wiedzieć, jak mogę rozwiązać tę sytuację.

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: deklaracja typ jest poniżej: -

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

wyjściowa dla pola identyfikatora jest: -

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

Odpowiedz

1

Najlepszym sposobem może być użycie niestandardowe powiązanie (klauzula javaType) z kompilatorem JAXB. Dokumentacja można znaleźć here. Zależnie od tego, czy musisz podwajać i eliminować podwojenia, rozwiązanie może być tak proste, jak nadpisanie mapowania do czegoś takiego, jak BigDecimal na poziomie globalnym (przy założeniu, że chociaż duble i cyfry dziesiętne są całkowicie różnymi rzeczami, wydaje Ci się, że chcesz mieć dziesiętny reprezentacja) lub użyć konwertera typów danych (powyższy link podaje przykłady wszystkich tych opcji).

+0

Podałeś konkretne przykłady? Czy uważasz, że opcja adaptera xml jest w porządku. Próbowałem użyć, jak pokazano powyżej w moim przykładzie JAxDouble Serialzer, ale nie jestem pewien, czego mi brakuje. – user1029083

7

Można użyć pliku an zewnętrzne powiązania tak:

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> 

korzeń.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 połączeń

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

głównej

Klasa generowany dla typu korzeniowego będzie miał XmlAdapter klas zarejestrowany na podwójnymi nieruchomości:

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 wykorzystuje metody skonfigurowanych w pliku 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

Dziękuję bardzo. Spróbuję w ten sposób. Nie mam pliku xsd, ale kod źródłowy jest generowany z pliku wsdl, który jest publikowany przez URL. Zakładam, że musiałbym użyć wsimport lub czegoś, co wiązałoby się z wsdl. xjc -d out -b binding.xml (http: //localhost/MyClient.wsdl) lub wsimport -d out -b binding.xml location.wsdl. – user1029083

Powiązane problemy