I have a Xml Like this
<entry>
<comboBox>
<name>xxx</name>
<details>sdfd</details>
</comboBox>
</entry>
In the other entry I have XML like this
<entry>
<numberField>
<name>xxx</name>
<details>sdfd</details>
</numberField>
</entry>
I want to map both comboBox and numberField to the same class in Java called Field
How do I annotate Java Fields in Entry Class?
In your Entry class you need to annotate the Java field with
#XmlElements
and list the individual element names there. Like this:
#XmlAccessorType(XmlAccessType.FIELD)
public class Entry {
#XmlElements({
#XmlElement(name = "comboBox", type = Field.class),
#XmlElement(name = "numberField", type = Field.class)
})
private Field field;
}
I have added type = Field.class in the annotation above only for clarity.
In your case you can omit it. Then JAXB will pick up Field from the property type decaration , which has the same desired effect.
The Field class can be straight-forward like this:
#XmlAccessorType(XmlAccessType.FIELD)
public class Field {
#XmlElement
private String name;
#XmlElement
private String details;
}
I think you should make two sub classes of an object which has the common annoted fields.
Each sub class just has to define jaxb #XmlRootElement (number field or combobox)
Related
I'm trying to parse existing XML files for a java application and some of the elements have mixed content occasionally as demonstrated below:
XML_STRING
<root>
<name>Michael</name>
<question>Text here</question>
</root>
XML_STRING_2
<root>
<name>Michael</name>
<question>Text here<measure>More Text</measure></question>
</root>
I Made the below classes to unmarshall this data.
Root Class
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Root implements Serializable
{
private String name;
private Question question;
}
Question Class
#XmlAccessorType(XmlAccessType.NONE)
public class Question implements Serializable
{
#XmlValue
private String questionText;
private String measure;
}
I can't seem to get both the Text Here and More Text to be stored inside the Question class.
JAXBContext.newInstance(Root.class)
.createUnmarshaller()
.unmarshal(new ByteArrayInputStream(XML_STRING_2.getBytes("UTF-8")));
I'm printing the result of the above code snippet (with Lombok's #ToString() annotation added to Root and Question) for both XML_STRING and XML_STRING_2.
XML_STRING: Root(name=Michael, question=Question(questionText=Text here, measure=null))
XML_STRING_2:Root(name=Michael, question=Question(questionText=, measure=null))
I was able to get something I could work with by using #XmlMixed along with #XmlElementRefs inside Question and creating a Measure class.
#XmlAccessorType(XmlAccessType.NONE)
public class Question implements Serializable
{
#XmlMixed
#XmlElementRefs({
#XmlElementRef(name = "measure", type=Measure.class)
})
private List<?> content;
}
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name="measure") // If this is removed I get the error: "Invalid #XmlElementRef : Type `Measure` or any of its subclasses are not known to this context."
public class Measure
{
#XmlValue
private String value;
}
I'm now getting the below output, which i can use via instanceof checking the items inside content
Root(name=Michael, question=Question(content=[Text here]))
Root(name=Michael, question=Question(content=[Text here, Measure(value=More Text)]))
The Root file remained unchanged.
I have a mapping from a DTO model to a JAXB generated datamodel that is full of JAXBElement<> wrapper objects.
For example, there is a class Person defined as (getters and setters are omitted):
public class Person {
private JAXBElement<Name> name;
}
Name is defined as:
public class Name {
private String value;
}
For constructing JAXBElement I created an ObjectFactory:
public class NameFactory extends ObjectFactory<JAXBElement<Name>> {
protected JAXBElement<Name> createObject(#Nonnull Class<?> context) {
// here, ObjectFactory is the JAXB generated ObjectFactory
return new ObjectFactory().createName();
}
}
In my ConfigurableMapper I create a class mapping from PersonDto to Person like so:
factory.createClassMap(PersonDto.class, Person.class)
.field("name", "name.value.value")
.register;
With this config, the mapping of a PersonDto with no name (name equals null) will result in a Person element that has a name member with its value set to null. This is probably better explained by showing the XML that is generated after performing the class mapping:
<Person>
<Name>
<value></value>
</Name>
</Person>
In my case, this XML is invalid, when there is a Name element, its value should always be non-null. The XML should therefore be:
<Person>
</Person>
Is it possible to prevent Orika from constructing the Name object, knowing its value will be set to null?
Going through the code again a day later with a clear mind, it turns out that Orika doesn't create the wrapper element (as I expected it wouldn't) and that it was a different issue entirely...
I'm able to unmurshal a single occurrence of a dynamic xml instantiating java classes (a wrapper and an adapter), but I don't understand how to extend this mechanism to a list of occurrences; the xml is like
<ALLRECORDSDATASET>
<RECORD>
<FIELD_0001>000248031</FIELD_0001>
<FIELD_0022>A</FIELD_0022>
<FIELD_0031>0</FIELD_0031>
<FIELD_0033>1994-01-01</FIELD_0033>
</RECORD>
<RECORD>
<FIELD_0001>000248056</FIELD_0001>
<FIELD_0027>ABC</FIELD_0027>
<FIELD_0037>DEF</FIELD_0037>
<FIELD_0040>1994-01-01</FIELD_0040>
</RECORD>
</ALLRECORDSDATASET>
and I can get the last values of RECORD (having a Record class containing a Fields class using #XmlAnyElement annotation), but I can't get all the RECORD list.
Can anyone help me? Thanks
Thats one way of doing that
#XmlRootElement(name = "ALLRECORDSDATASET")
#XmlAccessorType(XmlAccessType.NONE)
public class DataSet {
#XmlElements({ #XmlElement(name = "RECORD", type = Record.class) })
private List<Record> records;
}
#XmlAccessorType(XmlAccessType.NONE)
public class Record {
#XmlElement(name = "FIELD_0001")
private String field;
// ....
}
I have this class
public class Header {
#XmlAnyElement(lax = true)
protected List<Object> any;
// getters/setters omitted
}
How can I (in JAX-WS WebMethod) create an element ID in header that would look like this?
<Header>
<ID>value</ID>
</Header>
You could have a class like the following and add an instance of it into the any property, or you could add an instance of org.w3c.dom.Element representing the ID element to the collection.
#XmlRootElement(name="ID")
#XmlAccessorType(XmlAccessType.FIELD)
public class ID {
#XmlValue
private String value;
}
I have successfully marshaled the following class
#XmlRootElement(name = "Field")
private static class MyField {
#XmlAttribute(name = "Name")
String name;
#XmlElement(name = "Size")
int size;
....}
Now I want to have my container class to hold multiple instances of Field, so I declared a class in the following way:
private static class MyFieldsCollection {
private Collection<MyField> fields = new LinkedList<MyField>();
public MyFieldsCollection() {}
....}
When I simply try to marshal the container field I get the following error:
class java.util.LinkedList nor any of its super class is known to this context
How do I annotate the fields member so the container class will be marshaled as a collection of fields?
You shouldn't annotate your MyField class as a #XmlRootElement as it won't be a xml root element. I think you can either annotate it with #XmlType or simply do not annotate it. You could try and put the #XmlElement tag in the getter for the "fields" attribute in your class. If it works, your XML will look like this:
<MyFieldsCollection>
<fields name="name1" size="size1"/>
<fields name="name2" size="size2"/>
</MyFieldsCollection>
If it doesn't work, and it's a shot in the dark, try changing the type of the "Collection" to "List" to check if it makes some difference. What version of Java are you using? How does the code that you use to serialize your object looks like?