Unmarshalling with multiple namespaces
So let's say I have this xml with multiple namespaces.
<Envelope xmlns:pdi="http://www.mypage.com/schemas/pdi" xmlns:ib="http://www.mypage.com/schemas/ib" xmlns="http://www.mypage.com/schemas/envelope">
<Product>
<pdi:number>123456</pdi:number>
</Product>
<Instance>
<ib:serial>abcdefg</ib:serial>
</Instance>
</Envelope>
I am trying to create a client for it. I have a POJO envelope that is declared this way
@XmlRootElement(name ="Envelope", namespace = "http://www.mypage.com/schemas/envelope")
public class Envelope
and inside, it has these attributes
@XmlElement(name="Product", namespace = "http://www.mypage.com/schemas/pdi")
public Product getProduct(){...}
@XmlElement(name="Instance", namespace = "http://www.mypage.com/schemas/ib")
public Instance getInstance(){...}
In addition, the POJO product looks like this:
@XmlRootElement(name="Product", namespace = "http://www.mypage.com/schemas/pdi")
public class Product
and attribute
@XmlElement(name="pdi:number", namespace = "http://www.mypage.com/schemas/pdi")
public int getNumber(){...}
For some reason I cannot get the product number. I keep getting the request error. Am I handling namespaces correctly, or am I missing something?
source to share
In this case, I would recommend using package level annotation @XmlSchema
to indicate the qualifications of the namespace.
package-info (forum14651918 / package-info.java)
@XmlSchema(
namespace="http://www.mypage.com/schemas/envelope",
elementFormDefault=XmlNsForm.QUALIFIED,
xmlns={
@XmlNs(namespaceURI = "http://www.mypage.com/schemas/envelope", prefix = ""),
@XmlNs(namespaceURI = "http://www.mypage.com/schemas/ib", prefix = "ib"),
@XmlNs(namespaceURI = "http://www.mypage.com/schemas/pdi", prefix = "pdi")
}
)
@XmlAccessorType(XmlAccessType.FIELD)
package forum14651918;
import javax.xml.bind.annotation.*;
Envelope (forum14651918 / Envelope.java)
As we have indicated namespace
, and elementFormDefault
in the abstract @XmlSchema
, all items that match the class Envelope
will automatically qualify via the namespace http://www.mypage.com/schemas/envelope
.
package forum14651918;
import javax.xml.bind.annotation.*;
@XmlRootElement(name="Envelope")
public class Envelope {
@XmlElement(name="Product")
private Product product;
@XmlElement(name="Instance")
private Instance instance;
}
Product (forum14651918 / Product.java)
You can override the namespace for a class Product
using annotation @XmlType
.
package forum14651918;
import javax.xml.bind.annotation.*;
@XmlType(namespace="http://www.mypage.com/schemas/pdi")
public class Product {
private int number;
}
Instance (forum14651918 / Instance.java)
You can override the namespace for a class Instance
using annotation @XmlType
.
package forum14651918;
import javax.xml.bind.annotation.XmlType;
@XmlType(namespace="http://www.mypage.com/schemas/ib")
public class Instance {
private String serial;
}
Demo (forum14651918 / Demo.java)
Below is the code you can run to prove everything works.
import java.io.File;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Envelope.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum14651918/input.xml");
Envelope envelope = (Envelope) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(envelope, System.out);
}
}
Additional Information
source to share
Try replacing name="pdi:number", namespace = "http://www.mypage.com/schemas/pdi"
with name="number", namespace = "http://www.mypage.com/schemas/pdi"
. No prefix needed.
Looking more at XML, it seems that the namespace for Product
and Instance
is equal http://www.mypage.com/schemas/envelope
.
No Product
annotation is required for the class @XmlRootElement
. It is not a root element and is already set to getProduct()
.
Complete configuration that should be ok:
@XmlRootElement(name ="Envelope", namespace = "http://www.mypage.com/schemas/envelope")
public class Envelope {
@XmlElement(name="Product", namespace = "http://www.mypage.com/schemas/envelope")
public Product getProduct(){...}
@XmlElement(name="Instance", namespace = "http://www.mypage.com/schemas/envelope")
public Instance getInstance(){...}
}
public class Product {
@XmlElement(name="number", namespace = "http://www.mypage.com/schemas/pdi")
public int getNumber(){...}
}
public class Instance {
@XmlElement(name="serial", namespace = "http://www.mypage.com/schemas/ib")
public String getSerial(){...}
}
source to share