Reputation: 53
I'm working with JAXB and need to generate a XML code like this:
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!--Created with JFLAP 6.4.-->
<structure>
<type>fa</type>
<automaton>
<!--The list of states.-->
<state id="0" name="q0">
<x>160.0</x>
<y>151.0</y
<initial/> <!-- This what I want-->
</state>
<state id="1" name="q1">
<x>369.0</x>
<y>94.0</y>
<final/> <!-- This what I want-->
</state>
<!--The list of transitions.-->
<transition>
<from>0</from>
<to>1</to>
<read>a</read>
</transition>
</automaton>
</structure>
As you can see, I wanna know how to create a simple @XmlElement without @XmlAttribute, but in my code, I got:
private boolean initial = false;
private boolean final = false;
@XmlElement(name="initial")
public void setInitial(boolean val) {
this.initial = val;
}
@XmlElement(name="final")
public void setFinal(boolean val) {
this.final = val;
}
This way, I got a XML like this:
<state id="0" name="q0">
<x>0.0</x>
<y>0.0</y>
<final>false</final>
<initial>true</initial>
</state>
<state id="1" name="q1">
<x>0.0</x>
<y>0.0</y>
<final>true</final>
<initial>false</initial>
</state>
Does anyone knows how to do it?
Upvotes: 3
Views: 1844
Reputation: 17595
You could fake an empty node by setting an empty string, for this you need to turn your boolean
s to String
s.
@XmlRootElement
public static class Structure {
@XmlElement String type;
@XmlElement Automaton automaton;
public Structure() { automaton = new Automaton(); }
Structure(String t) { this(); type = t; }
}
public static class Automaton {
@XmlElement List<State> state;
public Automaton() { state = new ArrayList<>(); }
State addState(State s) {state.add(s); return s;};
}
public static class State {
@XmlAttribute String id, name;
@XmlElement double x, y;
@XmlElement String initial;
@XmlElement(name="final") String final_;
public State() {};
State(String id, String n, double x, double y)
{this.id = id; name = n; this.x = x; this.y = y;};
}
Create some data and marshal it:
@Test
public void jaxbEmptyEmlements() throws JAXBException {
JAXBContext c = JAXBContext.newInstance(Structure.class);
Marshaller m = c.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
m.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
Structure o = new Structure("fa");
o.automaton.addState(new State("0", "q0", 160d, 151d)).initial = "";
o.automaton.addState(new State("1", "q1", 369d, 94d)).final_ = "";
m.marshal(o, System.out);
}
This will output
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<structure>
<type>fa</type>
<automaton>
<state id="0" name="q0">
<x>160.0</x>
<y>151.0</y>
<initial></initial>
</state>
<state id="1" name="q1">
<x>369.0</x>
<y>94.0</y>
<final></final>
</state>
</automaton>
</structure>
Note that <initial></initial>
is the same as <initial/>
, same for final
.
Alternatively you could rethink the node for the state type and make an element <state-type>
and set it with the value an enum, for example enum StateType { INITIAL, FINAL}
or simply set it to the strings initial
or final
.
EDIT
Upvotes: 0
Reputation: 148977
You could do the following and leverage an XmlAdapter
to convert a Boolean
to an empty object to get the desired XML representation.
Root
The property is boolean
, but we will make the field Boolean
so we can apply an XmlAdapter
to it. We will also specify that we want JAXB to map to the field (see: http://blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html).
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {
@XmlJavaTypeAdapter(BooleanAdapter.class)
private Boolean foo = false;
@XmlJavaTypeAdapter(BooleanAdapter.class)
private Boolean bar = false;
public boolean isFoo() {
return foo;
}
public void setFoo(boolean foo) {
this.foo = foo;
}
public boolean isBar() {
return bar;
}
public void setBar(boolean bar) {
this.bar = bar;
}
}
BooleanAdapter
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class BooleanAdapter extends XmlAdapter<BooleanAdapter.AdaptedBoolean, Boolean> {
public static class AdaptedBoolean {
}
@Override
public Boolean unmarshal(AdaptedBoolean v) throws Exception {
return null != v;
}
@Override
public AdaptedBoolean marshal(Boolean v) throws Exception {
if(v) {
return new AdaptedBoolean();
} else {
return null;
}
}
}
Below is some demo code that you can run to see that everything works.
Demo
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Root.class);
Root foo = new Root();
foo.setFoo(true);
foo.setBar(false);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(foo, System.out);
}
}
Output
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
<foo/>
</root>
Upvotes: 1