JAXB更新XML元素

时间:2015-08-22 20:45:53

标签: java xml jaxb

我为需要创建和更新的JavaFX桌面应用程序提供了两个XML文件。经过一些研究,我发现JAXB是一个简单的解析器。

现在阅读工作正常,但是当我尝试更新XML元素时,它会引发异常:

  

线程“main”中的异常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>

1 个答案:

答案 0 :(得分:1)

加载XML文件时,您使用的是getResourceAsStream。这将查找相对于类文件位置的文件/storage/device.xml,或者当前目录。我现在记不清楚了。

当您尝试保存文件时,您使用的是名为FileOutputStream的{​​{1}}。在这种情况下,它将相对于文件系统的根目录。如果您没有目录/storage/device.xml,则系统无法保存您的文件。

示例DeviceDemo

/storage