2

I have an XML file like below, and I want to convert it into a Java object.

<P1>
    <CTS>
        Hello
    </CTS>
    <CTS>
        World
    </CTS>
<P1>    

So I created the following Java classes with their properties.

P1 class

@XmlRootElement
public class P1 {
    @XmlElement(name = "CTS")
    List<CTS> cts;
}

CTS class

public class CTS {
    String ct;
}

Test Class

File file = new File("D:\\ContentTemp.xml");
            JAXBContext jaxbContext = JAXBContext.newInstance(P1.class);
     
            Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
            P1 p = (P1) jaxbUnmarshaller.unmarshal(file);

But I am getting the following error:

com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException:
2 counts of IllegalAnnotationExceptions
Class has two properties of the same name "cts"

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Thinker
  • 6,820
  • 9
  • 27
  • 54

4 Answers4

4

com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException:
2 counts of IllegalAnnotationExceptions
Class has two properties of the same name "cts"

By default a JAXB (JSR-222) implementation creates mappings based on properties and annotated fields. When you annotate a field for which there is also a property it will cause this error.

You have two options:

  1. Use @XmlAccessorType(XmlAccessType.FIELD)

    You could annotate the field you need to specify @XmlAccessorType(XmlAccessType.FIELD) on the class.

    @XmlRootElement(name="P1)
    @XmlAccessorType(XmlAccessType.FIELD)
    public class P1 {
    
        @XmlElement(name = "CTS")
        List<CTS> cts;
    
    }
    
  2. Option #2 - Annotate the Property (get method)**

    Alternatively you could annotate the get method.

    @XmlRootElement(name="P1)
    public class P1 {
    
        List<CTS> cts;
    
        @XmlElement(name = "CTS")
        public List<CTS> getCts() {
            return cts;
        }
    
    }
    

For More Information


FULL EXAMPLE

CTS

You can use the @XmlValue annotation to map to Java class to a complex type with simple content.

@XmlAccessorType(XmlAccessType.FIELD)
public class CTS {

    @XmlValue
    String ct;

}

P1

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

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

    @XmlElement(name = "CTS")
    List<CTS> cts;

}

Demo

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

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(P1.class);
        
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("src/forum13987708/input.xml");
        P1 p1 = (P1) unmarshaller.unmarshal(xml);
        
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(p1, System.out);
    }
    
}

input.xml/Output

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<P1>
    <CTS>
        Hello
    </CTS>
    <CTS>
        World
    </CTS>
</P1>

For More Information

TylerH
  • 20,799
  • 66
  • 75
  • 101
bdoughan
  • 147,609
  • 23
  • 300
  • 400
0

Two issues I can see:

1) You need to use P1.class in your JAXBContext. You haven't said what the Presentation class is, but if your root element is P1, that's what you need in the context:

JAXBContext jaxbContext = JAXBContext.newInstance(P1.class);

2) You need to specify the name of the root xml element:

@XmlRootElement(name="P1")
public class P1 {
...
dogbane
  • 266,786
  • 75
  • 396
  • 414
  • this is right . I have changed the variable name .forgot to change it in test class. – Thinker Dec 21 '12 at 09:57
  • I can't reproduce your error because you haven't posted all the code. Do you have a method called `cts()` as well? If so, try renaming it to something else. – dogbane Dec 21 '12 at 10:00
  • no.this is whole my code. There is only getter and setters other than this code. The error showing is because it has two cts in xml file – Thinker Dec 21 '12 at 10:03
  • no, I have run the code you posted and it works for me. According to the error, you have two properties called `cts` in the class. It doesn't have anything to do with your xml. – dogbane Dec 21 '12 at 10:05
  • code run without error in your system? – Thinker Dec 21 '12 at 10:07
  • yes, I do not get any errors. Have you tried running the code you posted in the question? – dogbane Dec 21 '12 at 10:09
  • Yes. It is not working. Is there is any jar neeeded. Let me give this code to my friend and see it works. – Thinker Dec 21 '12 at 10:09
  • why do you have `@XmlElement(name = "CT")` in the CTS class? What is CT? – dogbane Dec 21 '12 at 10:13
0

Your XML looks like this:

<P1>
  <CTS>
    Hello
  </CTS>
  <CTS>
    World
  </CTS>
</P1>

But considering your mapping it should look like:

<p1>
  <CTS>
    <CT>
    Hello
    </CT>
  </CTS>
  <CTS>
    <CT>
    World
    </CT>
  </CTS>
</p1>

In order to change root element from p1 to P1 use attribute name from @XmlRootElement.

If you want to parse the first version of XML you posted, change your P1 class like this:

@XmlRootElement(name="P1")
public class P1 {
    @XmlElement(name = "CTS")
    List<String> cts;
 }
Florin
  • 201
  • 2
  • 5
  • 1
    FYI - You can map the object model to the XML given by @Thinker by leveraging the `@XmlValue` annotation: http://stackoverflow.com/a/13988362/383861 – bdoughan Dec 21 '12 at 10:53
0

You could try the following,

If you could, make xml as of the following structure.

<P1>
    <CTSList>
       <CTS value="Hello"/>
       <CTS value="World"/>
    </CTSList>
<P1>

And use,

@XMLRootElement(name="P1")
public class P1 {
  List CTSList;

  @XMLElementWrapper(name="CTSList")
  @XMLELement(name="CTS")
  public void setCTSList(List<CTS> ctsList) {
     this.CTSList = ctsList;
  }

  public List<CTS> getCTSList() {
    return this.CTSList;
  }
}

@XMLRootElement(name="CTS")
public class CTS {
   String cts;

   @XMLAttribute(name = "value")
   public String getCts() {
     return this.cts;
   }

   public void set setCts(String cts) {
     this.cts = cts;
   }
}
Senthil Kumar
  • 9,695
  • 8
  • 36
  • 45
  • FYI - You can map the object model to the XML given by @Thinker by leveraging the `@XmlValue` annotation: http://stackoverflow.com/a/13988362/383861 – bdoughan Dec 21 '12 at 11:17