3

I have searched all the questions related to this topic but i didnt find an answer to this. I am trying to convert an xml doc to java object. After searching for options to do the same, I found jaxb as the best option to do the same. I referred many articles and came up with this solution which is not working. Can somebody help me in this.

XML Dod:

<Vectors>
    <Vector>
        <Id>1</Id>
        <Name>abc</Name>
         <Desc>abcdefg</Desc>
         <Type>body</Type>
         <Snippet>
            <![CDATA[<total>1234</total>]]>
         </Snippet>
    </Vector>
    <Vector>
         <Id>2</Id>
         <Name>def</Name>
         <Desc>abcdefghigj</Desc>
         <Type>body</Type>
         <Snippet>
            <![CDATA[<total>12345</total>]]>
         </Snippet>
     </Vector>
</Vectors>

I want to create 2 java objects of class Vector. Class Vector looks as given below

    package com.abc.TryXmltoJava;

    import java.util.List;
    import javax.xml.bind.annotation.*;

    public class Vector {
        int Id,
        String Name;
        String Desc;
        String Type;

        @XmlElement
        public String getName() {
             return Name;
        }
        public void setName(String name) {
             this.Name = name;
        }

        @XmlElement
        public String getDesc() {
            return Desc;
        }
        public void setDesc(String desc) {
            this.Desc = desc;
        }

        @XmlElement
        public String getType() {
            return Type;
        }
        public void setType(String type) {
            this.Type = type;
        }
}

Now i have created Vectors class which keeps track of the two objects and creates a list of Vector objects using list utility..

 package com.abc.TryXMLtoObject;

 import javax.xml.bind.annotation.*;

 @XmlRootElement(name="Vectors")
 public class Vectors {

 @XmlElement(name="Vector")
     Vector vector;


     public Vector getVector() {
        return vector;
     }

     public void setVector(Vector vector1) {
        this.vector = vector1;
     }
}

I will try to unmarshall the xml object using these two classes which create a list of java objects. Unmarshalling class is as given below..

  package com.abc.TryXMLtoObject;

  import java.io.File;
  import javax.xml.bind.JAXBContext;
  import javax.xml.bind.JAXBException;
  import javax.xml.bind.Unmarshaller;

  public class JAXBExampleUnmarshal {

       public static void main(String[] args) {

         try {

          File file = new File("C:\\file.xml");
          JAXBContext jaxbContext = JAXBContext.newInstance(Vectors.class);

          Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
          Vectors vectors = (Vectors) jaxbUnmarshaller.unmarshal(file);
          System.out.println(vectors);

         } catch (JAXBException e) {
          e.printStackTrace();
         }

   }
 }

After running this code.. i get the following errors:

javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"Vectors"). Expected elements are (none)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(Unknown Source)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Unknown Source)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Unknown Source)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportUnexpectedChildElement(Unknown Source)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext$DefaultRootLoader.childElement(Unknown Source)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(Unknown Source)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(Unknown Source)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.startElement(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl$NSContentDriver.scanRootElementHook(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(Unknown Source)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(Unknown Source)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(Unknown Source)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(Unknown Source)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(Unknown Source)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(Unknown Source)
    at com.abc.TryXMLtoObject.JAXBExampleUnmarshal.main(JAXBExampleUnmarshal.java:17)
3
  • Try adding the namespace Commented Sep 20, 2012 at 7:49
  • Could this be a typo? (uri:"", local:"Vkectors"). "Vkectors" doesn't look right. Commented Sep 20, 2012 at 7:58
  • yup that was a typo.. but i am still getting the same error i.e local: "Vectors" Commented Sep 20, 2012 at 8:44

5 Answers 5

3

At first, you in Vectors you must have List<Vector> vectorList, not one singular Vector.
Also, text from stacktrace unexpected element (uri:"", local:"Vkectors") tells me, that somewhere in xml you have Vkectors element, and thats wrong.
Lastly, I strongly recommend you to put all annotations to get-methods, not to variable for two reasons: there was some name collision, if my memory is right, and secondly, if you'll have proxies from Hibernate or something like that, annotations from fields will disappear, but annotations for get-methods will stay.

Sign up to request clarification or add additional context in comments.

5 Comments

Oh.. Yes.. will check that and let you know, if it works or not
+1 - To avoid the name collision issue when annotating fields, @XmlAccessorType(XmlAccessType.FIELD) should be specified on the class: blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html
if you have annotated field field1 with @XmlElement, and you have method getField1(), than you'll get name collision. You can have annotated field1 with accessor getProperty1(){return field1;} though, but that seems to be ugly to me.
@popfalushi - Did you see my note about @XmlAccessorType(XmlAccessType.FIELD)?
My apologies. I saw that name of the field and accessors name differ and thought that it proves my point of view. Now checked it locally, and discovered that you are right.
2

The following version of your example worked for me:

Vectors

As pointed out by popfalushi, Vectors should have a List property that holds on to many instances of Vector.

package com.abc.TryXmltoJava;

import java.util.List;
import javax.xml.bind.annotation.*;

@XmlRootElement(name="Vectors")
@XmlAccessorType(XmlAccessType.FIELD)
public class Vectors {

    @XmlElement(name="Vector")
    List<Vector> vector;

}

Vector

If you wish to specify the JAXB annotations on the fields, then you should specify @XmlAccessorType(XmlAccessType.FIELD) at the type level (see: http://blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html). Also the default mapping is @XmlElement so you don't explicitly need to add that annotation (see: http://blog.bdoughan.com/2012/07/jaxb-no-annotations-required.html).

package com.abc.TryXmltoJava;

import javax.xml.bind.annotation.*;

@XmlAccessorType(XmlAccessType.FIELD)
public class Vector {
    int Id;
    String Name;
    String Desc;
    String Type;
}

JAXBExampleUnmarshal

I updated your demo code to write the objects back to XML, to prove that the objects were completely populated during the unmarshal operation.

package com.abc.TryXmltoJava;

import java.io.File;
import javax.xml.bind.*;

public class JAXBExampleUnmarshal {

    public static void main(String[] args) {

        try {
            File file = new File("C:\\file.xml");
            JAXBContext jaxbContext = JAXBContext.newInstance(Vectors.class);

            Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
            Vectors vectors = (Vectors) jaxbUnmarshaller.unmarshal(file);
            System.out.println(vectors);

            Marshaller marshaller = jaxbContext.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            marshaller.marshal(vectors, System.out);

        } catch (JAXBException e) {
            e.printStackTrace();
        }
    }

}

file.xml

<?xml version="1.0" encoding="UTF-8"?>
<Vectors>
    <Vector>
        <Id>1</Id>
        <Name>abc</Name>
         <Desc>abcdefg</Desc>
         <Type>body</Type>
         <Snippet>
            <![CDATA[<total>1234</total>]]>
         </Snippet>
    </Vector>
    <Vector>
         <Id>2</Id>
         <Name>def</Name>
         <Desc>abcdefghigj</Desc>
         <Type>body</Type>
         <Snippet>
            <![CDATA[<total>12345</total>]]>
         </Snippet>
     </Vector>
</Vectors>

Output

Below is the output from running the demo code:

com.abc.TryXmltoJava.Vectors@44fe9319
<?xml version="1.0" encoding="UTF-8"?>
<Vectors>
   <Vector>
      <Id>1</Id>
      <Name>abc</Name>
      <Desc>abcdefg</Desc>
      <Type>body</Type>
   </Vector>
   <Vector>
      <Id>2</Id>
      <Name>def</Name>
      <Desc>abcdefghigj</Desc>
      <Type>body</Type>
   </Vector>
</Vectors>

2 Comments

thanks a lot.. btw what this means "@XmlAccessorType(XmlAccessType.FIELD)"
@Sanket - By default a JAXB (JSR-222) implementation will create metadata for all public fields. If you want your JAXB (JSR-222) implementation to base the metadata on the fields instead you can specify @XmlAccesorType(XmlAccessType.FIELD). See: blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html
1

Instead of trying to restore objects could you first create them in Java and persist using JAXB? Then you'll see the difference between your XML file and the one JAXB produces.

Comments

1

First, your stack trace names Vekctors (note the k), so it might be a typo. But then it says "Expected elements are (none)". In your Vectors class you only have declared a Vector element, so it you can't put two elements inside the Vectors element.

Comments

1

You may wish to look at this answer that discusses hos to generate classes from an xsd. It also provides a link to a resource to generate an xsd from raw xml.

Your stack trace also refers to "Vkectors" - was their a typo in the source file?

Lastly, you may wish to start with the jaxb tutorial and work your way up from there.

Good luck!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.