简体   繁体   中英

How to unmarshal simple XML with single element and value

I'm try to unmarshal the following very simple XML received from an external web service using Spring's RestTemplate and JAXB:

<?xml version="1.0" encoding="utf-8"?>
<double xmlns="http://www.example.com/">0.061</double>

This is the class I'm using to unmarshal the XML. I've tried various combinations of @XmlRootElement, @XmlElement and @XmlValue, but can't get it to work.

@XmlRootElement
public class ExchangeRateWebServiceResponse {

    private double rate;

    @XmlElement(name = "double")
    public double getRate() {
        return rate;
    }

    public void setRate(double rate) {
        this.rate = rate;
    }    
}

The method which performs the web service call using RestTemplate:

public double getExchangeRate(String fromCurrency, String toCurrency, 
                              String exchangeRateURL) {
    RestTemplate restTemplate = new RestTemplate();

    ExchangeRateWebServiceResponse result = 
        restTemplate.getForObject(exchangeRateURL,
            ExchangeRateWebServiceResponse.class, 
                fromCurrency, toCurrency);

    return result.getRate();
}

This is the exception I am getting:

org.springframework.http.converter.HttpMessageNotReadableException: Could not unmarshal to [class za.co.example.server.finance.ExchangeRateWebServiceResponse]: unexpected element (uri:"http://www.example.com/", local:"double"). Expected elements are <{}exchangeRateWebServiceResponse>; nested exception is javax.xml.bind.UnmarshalException: unexpected element (uri:"http://www.example.com/", local:"double"). Expected elements are <{}exchangeRateWebServiceResponse>
at org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter.readFromSource(Jaxb2RootElementHttpMessageConverter.java:82)
at org.springframework.http.converter.xml.AbstractXmlHttpMessageConverter.readInternal(AbstractXmlHttpMessageConverter.java:61)
at org.springframework.http.converter.AbstractHttpMessageConverter.read(AbstractHttpMessageConverter.java:153)
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:103)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:496)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:452)
at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:222)
at za.co.example.server.finance.ExchangeRateWebService.getExchangeRate(ExchangeRateWebService.java:21)
at za.co.example.test.suites.integration.component.external.ExchangeRateWebserviceTests.testGetZARToGBPRate_shouldReturnAnExchangeRate(ExchangeRateWebserviceTests.java:18)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:77)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:195)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:63)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Caused by: javax.xml.bind.UnmarshalException: unexpected element (uri:"http://www.example.com/", local:"double"). Expected elements are <{}exchangeRateWebServiceResponse>
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:647)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:243)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:238)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportUnexpectedChildElement(Loader.java:105)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext$DefaultRootLoader.childElement(UnmarshallingContext.java:1048)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:483)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:465)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:135)
at org.apache.xerces.parsers.AbstractSAXParser.startElement(Unknown Source)
at org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanStartElement(Unknown Source)
at org.apache.xerces.impl.XMLNSDocumentScannerImpl$NSContentDispatcher.scanRootElementHook(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:203)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:175)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:157)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:125)
at org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter.readFromSource(Jaxb2RootElementHttpMessageConverter.java:74)
... 34 more

you need to have namespace at your java object.

@XmlElement(name = "double", namespace = "http://www.example.com/" )

EDIT

you can config your namespace in separate package-info class and place it in you java class package

@XmlSchema(
xmlns = { namespace = "http://www.example.com/",
elementFormDefault = XmlNsForm.QUALIFIED) 

so that you can have namespace defined only at root level, no need to defined at every xml element, you can also have multiple namespace configured.

this link will give more details about package-info.java

http://java.dzone.com/articles/jaxb-and-root-elements

With the help of @pappu_kutty, I worked out that I needed to specify the namespace and element name in @XmlRootElement, and then add @XmlValue to either getRate() or setRate() to get the value of the root element.

@XmlRootElement(name = "double", namespace = "http://www.example.com/")
public class ExchangeRateWebServiceResponse {

    private double rate;

    @XmlValue
    public double getRate() {
        return rate;
    }

    public void setRate(double rate) {
        this.rate = rate;
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM