0

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.

SarathSprakash
  • 4,614
  • 2
  • 19
  • 35
Gopal Singh
  • 44
  • 2
  • 9
  • Jaxb uses a parser under the hood, so you implicitly will use one already. What have you tried so far? Where did you get stuck? – stwissel Apr 30 '14 at 10:49
  • I dont have much command on Jaxb. Plz give ur email id. i will send my code to you. You could modify & send me again. I will gratefull for your help. – Gopal Singh Apr 30 '14 at 10:56
  • Not doing your homework. Does that XML really need to be like this? Having a part containing parts? Or is is it more like a partlist? – stwissel Apr 30 '14 at 11:27
  • Its a toll specific data. For example engine has cylinder, piston, screw, bolt etc. So engine will be considered parent part & piston, cylinder,.. all will be considered as child part. Cylinder has also child parts such as gear shaft, axial rod etc.. So i have to extract the data in the form of xml that can show the relation bw them. – Gopal Singh Apr 30 '14 at 11:32
  • Then your root part element needs to have the qualifying elements too! – stwissel Apr 30 '14 at 12:02
  • Does it work for you now? It is polite to upvote/accept helpful answers – stwissel Apr 30 '14 at 22:25

3 Answers3

1

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.

bdoughan
  • 147,609
  • 23
  • 300
  • 400
0

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

stwissel
  • 20,110
  • 6
  • 54
  • 101
  • 1
    You created the XML Schema, but then instead of generating a class model from it you built one by hand? The following article will help you get rid of the `@XmlTransient` annotations. – bdoughan Apr 30 '14 at 12:26
  • yeah, I played around with the annotations to refresh my memory how things work. Automation can only be appreciated when one knows what work it saves you. Found your blog quite enlightening. I'm aware of the Access Type. – stwissel Apr 30 '14 at 12:27
-1

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.

Community
  • 1
  • 1
Vinay Rao
  • 1,284
  • 9
  • 13