Jaxb: Unmarshalling xml with multiple namespaces in same package

前端 未结 1 1969
遥遥无期
遥遥无期 2020-12-30 04:12

I\'m new to using namespaces in xml so I am kind of confused and would like some clarification. I have a java service where I am receiving xml documents with many different

相关标签:
1条回答
  • 2020-12-30 04:56

    Below is an explanation of how namespaces work in JAXB (JSR-222) based on your model.

    JAVA MODEL

    package-info

    Below is a modified version of your @XmlSchema annotation. It contains some key information:

    • namespace - The default namespace that will be used to qualify global elements (those corresponding to @XmlRootElement and @XmlElementDecl annotations (and local elements based on the elementFormDefault value) that don't have another namespace specified.
    • elementFormDefault by default only global elements are namespace qualified but by setting the value to be XmlNsForm.QUALIFIED all elements without an explicit namespace specified will be qualified with the namespace value.
    • xmlns is the preferred set of prefixes that a JAXB impl should use for those namespaces (although they may use other prefixes).
    @XmlSchema(
        namespace="http://mycompany/train",
        elementFormDefault = XmlNsForm.QUALIFIED,
        xmlns={
           @XmlNs(prefix="train", namespaceURI="http://mycompany/train"), 
           @XmlNs(prefix="passenger", namespaceURI="http://mycompany/passenger")
       }
    )
    package forum15772478;
    
    import javax.xml.bind.annotation.*;
    

    Train

    Since all the elements corresponding to the Train class correspond to the namespace specified on the @XmlSchema annotation, we don't need to specify any namespace info.

    • Global Elements - The @XmlRootElement annotation corresponds to a global element.
    • Local Elements - The @XmlElementWrapper and @XmlElement annotations correspond to local elements.
    package forum15772478;
    
    import java.util.List;
    import javax.xml.bind.annotation.*;
    
    @XmlRootElement(name="Train")
    public class Train {
    
        private List<Passenger> passengers;
    
        @XmlElementWrapper(name="Passengers")
        @XmlElement(name="Passenger")
        public List<Passenger> getPassengers() {
            return passengers;
        }
    
        public void setPassengers(List<Passenger> passengers) {
            this.passengers = passengers;
        }
    
    }
    

    Passenger

    If all the elements corresponding to properties on the Passenger class will be in the http://mycompany/passenger namespace, then you can use the @XmlType annotation to override the namespace from the @XmlSchema annotation.

    package forum15772478;
    
    import javax.xml.bind.annotation.*;
    
    @XmlType(namespace="http://mycompany/passenger")
    public class Passenger {
    
        private String ticketNumber;
    
        @XmlElement(name="TicketNumber")
        public String getTicketNumber() {
            return ticketNumber;
        }
    
        public void setTicketNumber(String ticketNumber) {
            this.ticketNumber = ticketNumber;
        }
    
    }
    

    Alternatively you can override the namespace at the property level.

    package forum15772478;
    
    import javax.xml.bind.annotation.*;
    
    public class Passenger {
    
        private String ticketNumber;
    
        @XmlElement(
            namespace="http://mycompany/passenger",
            name="TicketNumber")
        public String getTicketNumber() {
            return ticketNumber;
        }
    
        public void setTicketNumber(String ticketNumber) {
            this.ticketNumber = ticketNumber;
        }
    
    }
    

    DEMO CODE

    The following demo code can be run to prove that everything works:

    Demo

    package forum15772478;
    
    import java.io.File;
    import javax.xml.bind.*;
    
    public class Demo {
    
        public static void main(String[] args) throws Exception {
            JAXBContext jc = JAXBContext.newInstance(Train.class);
    
            Unmarshaller unmarshaller = jc.createUnmarshaller();
            File xml = new File("src/forum15772478/input.xml");
            Train train = (Train) unmarshaller.unmarshal(xml);
    
            Marshaller marshaller = jc.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            marshaller.marshal(train, System.out);
        }
    
    }
    

    input.xml/Output

    In the XML below I have added the necessary namespace declarations that were missing from the XML document in your question.

    <train:Train 
       xmlns:train="http://mycompany/train" 
       xmlns:passenger="http://mycompany/passenger">
       <train:Color>Red</train:Color>
       <train:Passengers>
           <train:Passenger>
               <passenger:TicketNumber>T101</passenger:TicketNumber>
           </train:Passenger>
       </train:Passengers>
    </train:Train>
    

    FOR MORE INFORMATION

    • http://blog.bdoughan.com/2010/08/jaxb-namespaces.html
    0 讨论(0)
提交回复
热议问题