Reputation: 45
I have an XML that is generated by JAXB. See the XML file below
<config>
<instance>
<hostName>192.168.2.98</hostName>
<port>444</port>
</instance>
<instance>
<hostName>192.168.3.2</hostName>
<port>3333</port>
</instance>
<instance>
<hostName>192.168.1.168</hostName>
<port>168</port>
</instance>
</config>
Now , My plan is to modify the XML, following this steps:
the result should be like this
<config>
<instance>
<hostName>192.168.2.98</hostName>
<port>555</port>
</instance>
<instance>
<hostName>192.168.3.140</hostName>
<port>3333</port>
</instance>
<instance>
<hostName>192.168.1.130</hostName>
<port>8181</port>
</instance>
</config>
How to do that using JAXB? Should I umnmarshall it to the JAXBElement and pass it to Binder ?
FYI, I using HTML form to modify the XML files through JAX-RS. the resource post method below only work to create new instance, but not works for modify/update element value
@POST
@Path("/modhost")
@Consumes({ MediaType.APPLICATION_FORM_URLENCODED,
MediaType.APPLICATION_JSON })
@Produces(MediaType.APPLICATION_JSON)
public void modInstance(@FormParam("host") String hostX,
@FormParam("port") String portX) {
this.host = hostX;
this.port = portX;
try {
String env = System.getenv("APP_HOME");
String tesfile = env+"/tes2.xml";
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
File filex = new File(tesfile);
Document document = db.parse(filex);
JAXBContext jc = JAXBContext.newInstance(Config.class);
Binder<Node> binder = jc.createBinder();
Config config= (Config) binder.unmarshal(document);
Unmarshaller unmarshaller = jc.createUnmarshaller();
List<Instance> instList = new ArrayList<Instance>();
Instance inst = new Instance();
inst.setHostName(host);
inst.setPort(port);
instList.add(inst);
config.getInstance().addAll(instList);
binder.updateXML(config);
TransformerFactory tf = TransformerFactory.newInstance();
StreamResult result = new StreamResult(filex);
Transformer t = tf.newTransformer();
t.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "5");
t.setOutputProperty(OutputKeys.INDENT, "yes");
t.transform(new DOMSource(document), result);
} catch (TransformerConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JAXBException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (TransformerFactoryConfigurationError e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (TransformerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
here the JAXB classes Config and Instance
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = { "instances"})
@XmlRootElement(name = "config")
public class Config{
@XmlElement(required = true)
protected List<Instance> instance;
public List<Instance> getInstance() {
if (instance == null) {
instance = new ArrayList<Instance>();
}
return this.instance;
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = { "hostName", "port"})
@XmlRootElement(name = "instance")
public class Instances {
@XmlElement(required = true)
protected String hostName;
@XmlElement(required = true)
protected String port;
public String getHostName() {
return hostName;
}
public void setHostName(String value) {
this.hostName = value;
}
public String getPort() {
return port;
}
public void setPort(String value) {
this.port = value;
}
}
Upvotes: 2
Views: 9596
Reputation: 136062
I think this should work
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
class Config {
@XmlElement(name="instance", required = true)
protected List<Instance> instances;
public List<Instance> getInstances() {
return instances;
}
}
@XmlAccessorType(XmlAccessType.FIELD)
class Instance {
protected String hostName;
protected String port;
public String getHostName() {
return hostName;
}
public void setHostName(String value) {
this.hostName = value;
}
public String getPort() {
return port;
}
public void setPort(String value) {
this.port = value;
}
}
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Config.class);
Config config = (Config)jc.createUnmarshaller().unmarshal(new File("1.xml"));
List<Instances> list = config.getInstances();
list.get(0).setPort(555);
list.get(1).setHostName("192.168.3.140");
list.get(2).setPort(168);
list.get(2).setHostName("192.168.1.168");
Marshaller m = jc.createMarshaller();
m.marshal(config, filex);
Upvotes: 4