Java XML更新问题 - appendchild()没有成功附加元素

时间:2014-08-13 02:17:48

标签: java xml

当我将新节点附加到xml dom时,我遇到了问题。以下代码是xmlFactory.java中的dom保存代码。

import java.io.File;
import java.io.StringWriter;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;

import com.ism.msgmgt.domain.Post;
import com.ism.msgmgt.domain.User;


public class XmlFactory {

    private static Document userdom;
    private static Document postdom;

    private static File userfile = new File(User.class.getResource("User.xml").getPath());

    static {

        try{
            DocumentBuilderFactory dbuf = DocumentBuilderFactory.newInstance();
            DocumentBuilder dbu = dbuf.newDocumentBuilder();
            userdom = dbu.parse(userfile);
            DocumentBuilderFactory dbpf = DocumentBuilderFactory.newInstance();
            DocumentBuilder dbp = dbpf.newDocumentBuilder();
            postdom = dbp.parse(postfile);
        } catch (Exception e){
            e.printStackTrace();
        }
    }

    public static Document getUserDom(){
        return userdom;
    }

    public static void saveUserDom(){
        try {
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer trans = tf.newTransformer();
            System.out.println(userdom.getFirstChild()+"|"+userdom.getFirstChild().getFirstChild());
            DOMSource ds = new DOMSource(userdom);
            StreamResult sr = new StreamResult(userfile);
            trans.transform(ds, sr);
        } catch (Exception e){
            throw new RuntimeException(e.getMessage(),e);
        }
    }


}

请注意,打印输出为[users:null] | [#text:]。接下来,它是UserDao.java中的代码。

public class UserDao {

    public static Element currentUser = null;
    public static Document userdom = XmlFactory.getUserDom();

    public static void reg(User u){
        clrLogin();
        u.setUserid(UidUtil.getUid());
        u.setPassword(PwdUtil.encode(u.getPassword()));
        Element e = userdom.createElement("user");

        e.setAttribute("id", u.getUserid());
        e.setAttribute("username", u.getUsername());
        e.setAttribute("password", u.getPassword());
        e.setAttribute("login", u.getLogin());

        userdom.getFirstChild().appendChild(e);
        System.out.println(e);
        System.out.println(userdom.getFirstChild()+"|"+userdom.getFirstChild().getFirstChild());
        XmlFactory.saveUserDom();
        currentUser = e;
    }
}

请注意,在此代码中,我打印了我要添加的节点,即[user:null]。接下来,我打印了期待添加的节点。但是,我得到了结果[users:null] | [#text:],这与从上面的代码打印的输出相同。所以看起来appendChild()没有将e添加到dom的第一个节点。请帮忙。感谢。

XML文件

<?xml version="1.0" encoding="UTF-8"?>
<users>

</users>

1 个答案:

答案 0 :(得分:0)

你的问题中缺少太多的背景,因为我们不知道userdom是如何实际创建的......

让我用以下代码演示......

import java.io.ByteArrayOutputStream;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

public class Test1 {

    public static Document userdom;

    public static void main(String[] args) {
        try {
            userdom = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
            Element root = userdom.createElement("users");
            Node adoptNode = userdom.adoptNode(root);
            userdom.appendChild(adoptNode);

            reg();
        } catch (ParserConfigurationException | DOMException exp) {
            exp.printStackTrace();
        }
    }

    public static void reg() {
        Element e = userdom.createElement("user");

        e.setAttribute("id", "blah");
        e.setAttribute("username", "kermit");
        e.setAttribute("password", "bunnies in the air");
        e.setAttribute("login", "kermmi");

        userdom.getFirstChild().appendChild(e);
        System.out.println(e);
        System.out.println(userdom.getFirstChild() + "|" + userdom.getFirstChild().getFirstChild());
        saveUserDom();
    }

    public static void saveUserDom() {
        try {
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer trans = tf.newTransformer();
            System.out.println(userdom.getFirstChild() + "|" + userdom.getFirstChild().getFirstChild());
            DOMSource ds = new DOMSource(userdom);

            try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
                StreamResult sr = new StreamResult(baos);
                trans.transform(ds, sr);

                System.out.println(new String(baos.toByteArray()));
            }
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }
}

我得到以下输出......

[user: null]
[users: null]|[user: null]
[users: null]|[user: null]
<?xml version="1.0" encoding="UTF-8" standalone="no"?><users><user id="blah" login="kermmi" password="bunnies in the air" username="kermit"/></users>

这清楚地表明appendChild方法工作正常。

直接关注的是......之间的关系。

public static Document userdom = XmlFactory.getUserDom();

DOMSource ds = new DOMSource(userdom);

有人要问,它们是否相同(userdom)?

<强>更新

此...

 private static File userfile = new File(User.class.getResource("User.xml").getPath());

加上这个......

 StreamResult sr = new StreamResult(userfile);

你的问题......

首先,您正在加载内部资源,并且绝不应将这些内容包装在File条目中,内部/嵌入式资源无法从File上下文访问,需要以不同的方式加载,相反,保持getResource结果......

的网址引用
 private static URL userfile = User.class.getResource("User.xml");

下一行(StreamResult sr = new StreamResult(userfile);)正在尝试将生成的DOM写回嵌入式资源...无法以这种方式写入嵌入式资源,因此它会在正常运行时失败环境(它可能适用于您的IDE,但这是一个不同的问题)。

基本上,您无法将此信息作为嵌入式资源进行维护,您需要将文件外部化到磁盘上。

供参考:

如果您确实正确使用了资源的URL,则需要将XML文档的加载方式更改为...

try (InputStream is = userfile.openStream()) {
    userdom = dbu.parse(is);
}