[英]JAXB update XML elements
我為需要創建和更新的JavaFX桌面應用程序獲取了兩個XML文件。 經過一番研究,我發現JAXB可以輕松完成這項工作。
現在閱讀可以正常工作,但是當我嘗試更新XML元素時,它將引發異常:
線程“主”中的異常java.io.FileNotFoundException:\\ storage \\ device.xml(系統找不到指定的路徑)
我也嘗試使用屬性文件,但是感覺與我需要的層次結構不對應。
JAXB是否不是更新XML文件中現有元素的方法,還是在這種情況下需要使用DOM解析器?
現在,我已經苦苦掙扎了數小時,沒有任何解決方案。 我使用Maven,XML文件存儲在資源文件夾內的存儲文件夾中。 有關更多信息,請參見下面的代碼示例。
歡迎提供解決此問題的所有反饋,建議或任何其他解決方案(其他存儲解決方案?)。
也許您知道一些更好的解決方案來處理這兩個XML文件?
先感謝您!
DeviceDemo.java
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
public class DeviceDemo {
public static void main(String[] args) throws Exception {
// Initialize
String file = "/storage/device.xml";
JAXBContext jaxbContext = JAXBContext.newInstance(Device.class);
// Read
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
InputStream inputStream = DeviceDemo.class.getResourceAsStream(file);
Device device = (Device) unmarshaller.unmarshal(inputStream);
inputStream.close();
// Update
device.setName("Updated name");
device.setHost("Updated host");
device.setPort(2302);
Marshaller marshaller = jaxbContext.createMarshaller();
OutputStream outputStream = new FileOutputStream(file);
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(device, outputStream);
outputStream.close();
}
}
設備
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
@XmlRootElement(name = "device")
@XmlType(propOrder = {
"name",
"host",
"port"
})
public class Device {
private String name;
private String host;
private Integer port;
public String getName() {
return name;
}
@XmlElement(name = "name")
public void setName(String name) {
this.name = name;
}
public String getHost() {
return host;
}
@XmlElement(name = "host")
public void setHost(String host) {
this.host = host;
}
public Integer getPort() {
return port;
}
@XmlElement(name = "port")
public void setPort(Integer port) {
this.port = port;
}
@Override
public String toString() {
return name + " " + host + " " + port;
}
}
Device.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<device>
<name>Device</name>
<host>host.com</host>
<port>80</port>
</device>
CommandsDemo.java
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
public class CommandsDemo {
public static void main(String[] args) throws Exception {
// Initialize
String file = "/storage/commands.xml";
JAXBContext jaxbContext = JAXBContext.newInstance(Commands.class);
// Read
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
InputStream inputStream = CommandsDemo.class.getResourceAsStream(file);
Commands commands = (Commands) unmarshaller.unmarshal(inputStream);
inputStream.close();
// Print all commands
List<Command> commandsList = commands.getCommands();
for (Command command : commandsList) {
System.out.println(command.toString());
}
// Update a specific command
for (Command command : commandsList) {
if (command.getName().equals("Power on")) {
command.setName("Updated name");
command.setHost("Updated host");
command.setUser("Updated user");
command.setPassword("Updated password");
command.setTimeout(3439);
command.setPort(33223);
command.setCommand("Updated command");
Marshaller marshaller = jaxbContext.createMarshaller();
OutputStream outputStream = new FileOutputStream(file);
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(command, outputStream);
outputStream.close();
}
}
}
}
Commands.java
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.List;
@XmlRootElement(name = "commands")
public class Commands {
private List<Command> commands;
public List<Command> getCommands() {
return commands;
}
@XmlElement(name = "command")
public void setCommands(List<Command> commands) {
this.commands = commands;
}
@Override
public String toString() {
return commands.toString();
}
}
Command.java
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
@XmlRootElement(name = "command")
@XmlType(propOrder = {
"name",
"host",
"user",
"password",
"port",
"timeout",
"command"
})
public class Command {
private String name;
private String host;
private String user;
private String password;
private Integer port;
private Integer timeout;
private String command;
public String getName() {
return name;
}
@XmlElement(name = "name")
public void setName(String name) {
this.name = name;
}
public String getHost() {
return host;
}
@XmlElement(name = "host")
public void setHost(String host) {
this.host = host;
}
public String getUser() {
return user;
}
@XmlElement(name = "user")
public void setUser(String user) {
this.user = user;
}
public String getPassword() {
return password;
}
@XmlElement(name = "password")
public void setPassword(String password) {
this.password = password;
}
public Integer getPort() {
return port;
}
@XmlElement(name = "port")
public void setPort(Integer port) {
this.port = port;
}
public Integer getTimeout() {
return timeout;
}
@XmlElement(name = "timeout")
public void setTimeout(Integer timeout) {
this.timeout = timeout;
}
public String getCommand() {
return command;
}
@XmlElement(name = "command")
public void setCommand(String command) {
this.command = command;
}
@Override
public String toString() {
return name + " " + host + " " + user + " " + password + " " + port + " " + timeout + " " + command;
}
}
Commands.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<commands>
<command>
<name>Power on</name>
<host>host.com</host>
<user>user</user>
<password>password</password>
<port>22</port>
<timeout>10000</timeout>
<command>power on commando</command>
</command>
<command>
<name>Power off</name>
<host>host.com</host>
<user>user</user>
<password>password</password>
<port>22</port>
<timeout>10000</timeout>
<command>power off command</command>
</command>
</commands>
加載XML文件時,您正在使用getResourceAsStream
。 這將查找相對於類文件或當前目錄位置的文件/storage/device.xml
。 我現在不記得確切。
嘗試保存文件時,您使用的是具有相同名稱/storage/device.xml
FileOutputStream
。 在這種情況下,它將相對於文件系統的根目錄。 如果那里沒有目錄/storage
,則系統將無法保存文件。
DeviceDemo示例
public class DeviceDemo {
public static void main(String[] args) throws Exception {
// Initialize
// On unix this will result in the equivalent of $HOME/.powercontrol/storage/device.xml
Path file = Paths.get(System.getProperty("user.home"), ".powercontrol", "storage", "device.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(Device.class);
// Read
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
InputStream inputStream = new FileInputStream(file.toFile);
Device device = (Device) unmarshaller.unmarshal(inputStream);
inputStream.close();
// Update
device.setName("Updated name");
device.setHost("Updated host");
device.setPort(2302);
// Write
Marshaller marshaller = jaxbContext.createMarshaller();
OutputStream outputStream = new FileOutputStream(file.toFile);
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(device, outputStream);
outputStream.close();
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.