Question

I want to read or write multi-level Xml file via Jaxb (cannot use xml parser). For example one part(considered as parent part) has many child part. That child part also has child parts. So the structure is like this which I have created manually.

 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<part xmlns="http://www.serus.com">
    <part>
        <Part_Number>n0</Part_Number>
        <Part_Version>revision0</Part_Version>
        <Part_Type>p0</Part_Type>
        <Status>current0</Status>
    </part>
    <part>

        <Part_Number>n1</Part_Number>
        <Part_Version>revision1</Part_Version>
        <Part_Type>p1</Part_Type>
        <Status>current1</Status>

         <part>
            <Part_Number>n2</Part_Number>
            <Part_Version>revision2</Part_Version>
            <Part_Type>p2</Part_Type>
            <Status>current2</Status>

             <part>
                <Part_Number>n3</Part_Number>
                <Part_Version>revision3</Part_Version>
                <Part_Type>p3</Part_Type>
                <Status>current3</Status>
            </part>

        </part>


    <part>
        <Part_Number>n3</Part_Number>
        <Part_Version>revision3</Part_Version>
        <Part_Type>p3</Part_Type>
        <Status>current3</Status>
    </part>

    </part>

    <part>
        <Part_Number>n4</Part_Number>
        <Part_Version>revision4</Part_Version>
        <Part_Type>p4</Part_Type>
        <Status>current4</Status>
    </part>
</part>

I have to perform marshalling & Unmarshalling for such kind of data. This is the project requirement. As of my knowledge, in jaxb I have set of classes. I have to created some methods, so that I can perform this via java program.

Please help me. I will appreaciate for your suggestions & answers.

Was it helpful?

Solution

Your Java model is going to look something like the following. A Part class that holds onto a list of other Part instances as well as some other data.

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Part {

    @XmlElement(name="Part_Number");
    private String partNo;

    @XmlElement(name="part")
    private List<Part> parts;

}

You may find the following articles from my blog helpful:

Namespace Qualification

Since your XML document is namespace qualified you are going to need to factor this into your mapping metadata. I would recommend doing this with the package level @XmlSchema annotation.

OTHER TIPS

I presume there was a copy error in your XML. Either your root element is <partlist> or it is missing the elements Part_Number, Part_Version, Part_Type and Status (that would make sense). So your schema would look like this:

    <?xml version="1.0" encoding="UTF-8"?>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://www.serus.com" xmlns:ns1="http://www.serus.com">
      <xs:element name="part">
        <xs:complexType> 
          <xs:sequence minOccurs="1" maxOccurs="1">
            <xs:element ref="ns1:Part_Number"/>
            <xs:element ref="ns1:Part_Type"/>
            <xs:element ref="ns1:Part_Version"/>
            <xs:element ref="ns1:Status"/>
            <xs:choice minOccurs="0" maxOccurs="unbounded">
              <xs:element ref="ns1:part"/>
            </xs:choice>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
      <xs:element name="Part_Number" type="xs:NCName"/>
      <xs:element name="Part_Type" type="xs:NCName"/>
      <xs:element name="Part_Version" type="xs:NCName"/>
      <xs:element name="Status" type="xs:NCName"/>
    </xs:schema>

Then a class would have this format:

    import java.io.ByteArrayOutputStream;
    import java.io.InputStream;
    import java.io.Serializable;
    import java.util.ArrayList;
    import java.util.Collection;

    import javax.xml.bind.JAXBContext;
    import javax.xml.bind.JAXBException;
    import javax.xml.bind.Marshaller;
    import javax.xml.bind.Unmarshaller;
    import javax.xml.bind.annotation.XmlElement;
    import javax.xml.bind.annotation.XmlRootElement;
    import javax.xml.bind.annotation.XmlTransient;

    @XmlRootElement(name = "part")
    public class Part implements Serializable {

        public static Part fromXML(InputStream in) throws Exception {
            JAXBContext context = JAXBContext.newInstance(Part.class);
            Unmarshaller um = context.createUnmarshaller();
            return (Part) um.unmarshal(in);
        }

        private static final long   serialVersionUID    = 1L;
        @XmlElement(name = "Part_Number")
        private String              partNumber;
        @XmlElement(name = "Part_Type")
        private String              partType;
        @XmlElement(name = "Part_Version")
        private String              partVersion;
        @XmlElement(name = "Status")
        private String              status;
        @XmlElement(name = "part")
        private Collection<Part>    subParts            = null;

        public static void main(String args[]) throws JAXBException {
            Part mainPart = new Part("1m", "mType", "version 1", "draft");
            Part level1 = new Part("l1", "l1Type", "version 11", "new");
            level1.addPart(new Part("l2", "l2Type", "version 1", "new"));
            level1.addPart(new Part("l2-2", "l2Type", "version 1", "new"));
            mainPart.addPart(level1);
            System.out.println(mainPart.toXML());
        }

        public Part() {
            // No action here
        }

        public Part(String no, String type, String ver, String stat) {
            this.partNumber = no;
            this.partType = type;
            this.partVersion = ver;
            this.status = stat;
        }

        @XmlTransient
        public String getPartNumber() {
            return this.partNumber;
        }

        public void setPartNumber(String partNumber) {
            this.partNumber = partNumber;
        }

        @XmlTransient
        public String getPartType() {
            return this.partType;
        }

        public void setPartType(String partType) {
            this.partType = partType;
        }

        @XmlTransient
        public String getPartVersion() {
            return this.partVersion;
        }

        public void setPartVersion(String partVersion) {
            this.partVersion = partVersion;
        }

        @XmlTransient
        public String getStatus() {
            return this.status;
        }

        public void setStatus(String status) {
            this.status = status;
        }

        @XmlTransient
        public Collection<Part> getSubparts() {
            return this.subParts;
        }

        public void setSubparts(Collection<Part> subparts) {
            this.subParts = subparts;
        }

        public void addPart(Part part) {
            if (this.subParts == null) {
                this.subParts = new ArrayList<Part>();
            }
            this.subParts.add(part);
        }

        public void addParts(Collection<Part> parts) {
            if (this.subParts == null) {
                this.subParts = new ArrayList<Part>();
            }

            this.subParts.addAll(parts);
        }

        public String toXML() throws JAXBException {
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            JAXBContext context = JAXBContext.newInstance(Part.class);
            Marshaller m = context.createMarshaller();
            m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
            m.marshal(this, out);
            return out.toString();
        }

    }

The trick here is the strategic use of @XmlElement(name = "part") and @XmlTransient. That should do the trick

You need not even create the Java obejcts manually, if you have the xsd for your xml. Check this one out - How to generate JAXB classes from XSD?. Marshalling and unmarshalling - try out http://www.mkyong.com/java/jaxb-hello-world-example/.

You should really try out something and then ask questions if you are stuck at some point. That would make the responses very specific to the problem.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top