I'm trying to use SimpleXmlConverterFactory with Retrofit to create an XML request to a REST service. However, the service requires the DTD declaration in the request like so.
<!DOCTYPE paymentService PUBLIC "-//WorldPay//DTD WorldPay PaymentService v1//EN" "http://dtd.worldpay.com/paymentService_v1.dtd">
But when SimpleXmlConverterFactory serializes the data objects, it leaves off the DOCTYPE declaration:
<paymentService merchantCode="..." version="1.4">
<inquiry>
<shopperTokenRetrieval>
<authenticatedShopperID>...</authenticatedShopperID>
</shopperTokenRetrieval>
</inquiry>
</paymentService>
Creating the SimpleXmlConverterFactory isn't anything special:
val builder = Retrofit
.Builder()
.addConverterFactory(
SimpleXmlConverterFactory.create()
)
.baseUrl(BuildConfig.WORLDPAY_BASE_URL)
.build()
.create(WorldPayApiService::class.java)
And here is the annotated data object
@Root(name = "paymentService")
data class WorldPayXmlPaymentService(
@field:Attribute(name = "version")
var version: String = "",
@field:Attribute(name = "merchantCode")
var merchantCode: String = "",
@field:Element(name = "reply", required = false)
var reply: WorldPayXmlReply? = null,
@field:Element(name = "inquiry", required = false)
var inquiry: WorldPayXmlInquiry? = null
)
I added an override of a Persister as a parameter to the SimpleXmlConverterFactory.create method, like the following. It looks for the root element and then outputs the DOCTYPE before serializing the rest.
val persister = object : Persister() {
@Throws(Exception::class)
override fun write(source: Any, out: Writer) {
(source as? WorldPayXmlPaymentService)?.let {
val docType = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<!DOCTYPE paymentService PUBLIC \"-//WorldPay//DTD WorldPay PaymentService v1//EN\" \"http://dtd.worldpay.com/paymentService_v1.dtd\">"
out.write(docType)
super.write(source, out)
}
}
}
val builder = Retrofit
.Builder()
.addConverterFactory(
SimpleXmlConverterFactory.create(persister)
)
.baseUrl(BuildConfig.WORLDPAY_BASE_URL)
.build()
.create(WorldPayApiService::class.java)
where WorldPayXmlPaymentService is my root data object.
Thanks to @CommonsWare for the guidance.
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.