Skip to main content

@Xml(format) Annotation

The @Xml(format) annotation can be used to tweak the XML format of a POJO. The value is set to an enum value of type XmlFormat. This annotation can be applied to both classes and bean properties. The XmlFormat.ATTR format can be applied to bean properties to serialize them as XML attributes instead of elements. Note that this only supports properties of simple types (e.g. strings, numbers, booleans).

Example
Data typeJSON exampleWithout annotationWith annotation
class MyBean {
@Xml(format=XmlFormat.ATTR)
public String a;
}
{
a: 'foo'
}
<object>
<a>foo</a>
</object>
<object a='foo'/>

The XmlFormat.ATTRS format can be applied to bean classes to force all bean properties to be serialized as XML attributes instead of child elements.

Example
Data typeJSON exampleWithout annotationWith annotation
@Xml(format=XmlFormat.ATTRS)
class MyBean {
public String a;
public int b;
}
{
a: 'foo',
b: 123
}
<object>
<a>foo</a>
<b>123</b>
</object>
<object a='foo' b='123'/>

The XmlFormat.ELEMENT format can be applied to bean properties to override the XmlFormat.ATTRS format applied on the bean class.

Example
Data typeJSON exampleWithout annotationWith annotation
@Xml(format=XmlFormat.ATTRS)
class MyBean {
public String a;
@Xml(format=XmlFormat.ELEMENT)
public int b;
}
{
a: 'foo',
b: 123
}
<object>
<a>foo</a>
<b>123</b>
</object>
<object a='foo'>
<b>123</b>
</object>

The XmlFormat.ATTRS format can be applied to a single bean property of type Map to denote arbitrary XML attribute values on the element. These can be mixed with other XmlFormat.ATTR annotated properties but there must not be an overlap in bean property names and map keys.

Example
Data typeJSON exampleWithout annotationWith annotation
class MyBean {
@Xml(format=XmlFormat.ATTRS)
public Map<String,Object> a;
@Xml(format=XmlFormat.ATTR)
public int b;
}
{
a: {
k1: 'foo',
k2: 123
},
b: 456
}
<object>
<a>
<k1>foo</k1>
<k2 _type='number'>123</k2>
</a>
<b>456</b>
</object>
<object k1='foo' k2='123' b='456'/>

The XmlFormat.COLLAPSED format can be applied to bean properties of type array/Collection. This causes the child objects to be serialized directly inside the bean element. This format must be used in conjunction with @Xml(childName) to differentiate which collection the values came from if you plan on parsing the output back into beans. Note that child names must not conflict with other property names.

Data typeJSON exampleWithout annotationWith annotation
class MyBean {
@Xml(childName="A",format=XmlFormat.COLLAPSED)
public String[] a;
@Xml(childName="B",format=XmlFormat.COLLAPSED)
public int[] b;
}
{
a: ['foo','bar'],
b: [123,456]
}
<object>
<a>
<string>foo</string>
<string>bar</string>
</a>
<b>
<number>123</number>
<number>456</number>
</b>
</object>
<object>
<A>foo</A>
<A>bar</A>
<B>123</B>
<B>456</B>
</object>

The XmlFormat.ELEMENTS format can be applied to a single bean property of either a simple type or array/Collection. It allows free-form child elements to be formed. All other properties on the bean MUST be serialized as attributes.

Data typeJSON exampleWith annotation
class MyBean {
@Xml(format=XmlFormat.ATTR)
public String a;
@Xml(format=XmlFormat.ELEMENTS)
public String b;
}
{
a: 'foo',
b: 'bar'
}
<object a='foo'>
bar
</object>
class MyBean {
@Xml(format=XmlFormat.ATTR)
public String a;
@Xml(format=XmlFormat.ELEMENTS)
public Object[] b;
}
{
a: 'foo',
b: ['bar', 'baz', 123, true, null]
}
<object a='foo'>
bar
baz
123
true
</object>

The XmlFormat.MIXED format is similar to XmlFormat.ELEMENTS except elements names on primitive types (string/number/boolean/null) are stripped from the output. This format particularly useful when combined with bean dictionaries to produce mixed content. The bean dictionary isn't used during serializationbut it is needed during parsing to resolve bean types. The XmlFormat.MIXED_PWS format identical to XmlFormat.MIXED except whitespace characters are preserved in the output.

Data typeJSON exampleWithout annotationsWith annotations
class MyBean {
@Xml(format=XmlFormat.MIXED)
@Beanp(dictionary={MyBeanX.class, MyBeanY.class})
public Object[] a;
}

@Bean(typeName="X")
class MyBeanX {
@Xml(format=XmlFormat.ATTR)
public String b;
}

@Bean(typeName="Y")
class MyBeanY {
@Xml(format=XmlFormat.ATTR)
public String c;
}
{
a: [
'foo',
{ _type:'X', b:'bar' },
'baz',
{ _type:'Y', c:'qux' },
'quux'
]
}
<object>
<a>
<string>foo</string>
<object>
<b>bar</b>
</object>
<string>baz</string>
<object>
<c>qux</c>
</object>
<string>quux</string>
</a>
</object>
<object>
foo<X b='bar'/>baz<Y c='qux'/>quux
</object>

Whitespace (tabs and newlines) are not added to MIXED child nodes in readable-output mode. This helps ensures strings in the serialized output can be losslessly parsed back into their original forms when they contain whitespace characters. If the XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES setting was not useless in Java, we could support lossless readable XML for MIXED content. But as of Java 8, it still does not work. XML suffers from other deficiencies as well that affect MIXED content. For example, and are equivalent in XML and indistinguishable by the Java XML parsers. This makes it impossible to differentiate between an empty element and an element containing an empty string. This causes empty strings to get lost in translation. To alleviate this, we use the constructs "xE000" to represent an empty string, and "x0020" to represent leading and trailing spaces. The examples below show how whitespace is handled under various circumstances:

Data typeXML
@Bean(typeName="X")
class MyBean {
@Xml(format=XmlFormat.TEXT)
public String a = null;
}
<X/>
@Bean(typeName="X")
class MyBean {
@Xml(format=XmlFormat.TEXT)
public String a = "";
}
<X>_xE000_</X>
@Bean(typeName="X")
class MyBean {
@Xml(format=XmlFormat.TEXT)
public String a = " ";
}
<X>_x0020_</X>
@Bean(typeName="X")
class MyBean {
@Xml(format=XmlFormat.TEXT)
public String a = " ";
}
<X>_x0020__x0020_</X>
@Bean(typeName="X")
class MyBean {
@Xml(format=XmlFormat.TEXT)
public String a = " foobar ";
}
<X>_x0020_ foobar _x0020_</X>
@Bean(typeName="X")
class MyBean {
@Xml(format=XmlFormat.TEXT_PWS)
public String a = null;
}
<X/>
@Bean(typeName="X")
class MyBean {
@Xml(format=XmlFormat.TEXT_PWS)
public String a = "";
}
<X>_xE000_</X>
@Bean(typeName="X")
class MyBean {
@Xml(format=XmlFormat.TEXT_PWS)
public String a = " ";
}
<X> </X>
@Bean(typeName="X")
class MyBean {
@Xml(format=XmlFormat.TEXT_PWS)
public String a = " ";
}
<X>  </X>
@Bean(typeName="X")
class MyBean {
@Xml(format=XmlFormat.TEXT_PWS)
public String a = " foobar ";
}
<X>  foobar  </X>
@Bean(typeName="X")
class MyBean {
@Xml(format=XmlFormat.MIXED)
public String[] a = null;
}
<X/>
@Bean(typeName="X")
class MyBean {
@Xml(format=XmlFormat.MIXED)
public String[] a = {""};
}
<X>_xE000_</X>
@Bean(typeName="X")
class MyBean {
@Xml(format=XmlFormat.MIXED)
public String[] a = {" "};
}
<X>_x0020_</X>
@Bean(typeName="X")
class MyBean {
@Xml(format=XmlFormat.MIXED)
public String[] a = {" "};
}
<X>_x0020__x0020_</X>
@Bean(typeName="X")
class MyBean {
@Xml(format=XmlFormat.MIXED)
public String[] a = {" foobar "};
}
<X>_x0020_ foobar _x0020_</X>
@Bean(typeName="X")
class MyBean {
@Xml(format=XmlFormat.MIXED_PWS)
public String[] a = null;
}
<X/>
@Bean(typeName="X")
class MyBean {
@Xml(format=XmlFormat.MIXED_PWS)
public String[] a = {""};
}
<X>_xE000_</X>
@Bean(typeName="X")
class MyBean {
@Xml(format=XmlFormat.MIXED_PWS)
public String[] a = {" "};
}
<X> </X>
@Bean(typeName="X")
class MyBean {
@Xml(format=XmlFormat.MIXED_PWS)
public String[] a = {" "};
}
<X>  </X>
@Bean(typeName="X")
class MyBean {
@Xml(format=XmlFormat.MIXED_PWS)
public String[] a = {" foobar "};
}
<X>  foobar  </X>

It should be noted that when using MIXED, you are not guaranteed to parse back the exact same content since side-by-side strings in the content will end up concatenated when parsed.

The XmlFormat.TEXT format is similar to XmlFormat.MIXED except it's meant for solitary objects that get serialized as simple child text nodes. Any object that can be serialize to a String can be used. The XmlFormat.TEXT_PWS is the same except whitespace is preserved in the output.

Data typeJSON exampleWithout annotationsWith annotations
class MyBean {
@Xml(format=XmlFormat.TEXT)
public String a;
}
{
a: 'foo'
}
<object>
<a>foo</a>
</object>
<object>
foo
</object>

The XmlFormat.XMLTEXT format is similar to XmlFormat.TEXT except it's meant for strings containing XML that should be serialized as-is to the document. Any object that can be serialize to a String can be used. During parsing, the element content gets parsed with the rest of the document and then re-serialized to XML before being set as the property value. This process may not be perfect (e.g. double quotes may be replaced by single quotes, etc...).

Data typeJSON exampleWith TEXT annotationWith XMLTEXT annotation
class MyBean {
@Xml(format=XmlFormat.XMLTEXT)
public String a;
}
{
a: 'Some <b>XML</b> text'
}
<object>
Some &lt;b&gt;XML&lt;/b&gt; text
</object>
<object>
Some <b>XML</b> text
</object>