Java插入XML节点时属性值丢失问题求助
问题:合并XML节点时属性值全部丢失
我尝试将一个XML文档中的一组节点插入到另一个XML文档的指定节点中,按照相关方案实现后,却发现导入的节点所有属性值都被移除了。
示例XML
XML1(目标文档)
<letterContent> <key1>key1</key1> <key2>key2</key2> <type>456</type> <object1>789</object1> <effectiveDate>00</effectiveDate> <expandedData attr1="case1"> <expandedData attr2="value2"> <data attrD="VD2">value D2</data> </expandedData> <expandedData attr3="value3"> <data attrD="vd3">value D3</data> </expandedData> </expandedData> </letterContent>
XML2(待插入的节点)
<expandedData attr4="value4"> <data attrd4="vd4">value d4</data> <name nameattr="specific_name"/> </expandedData>
期望结果
<letterContent> <key1>key1</key1> <key2>key2</key2> <type>456</type> <object1>789</object1> <effectiveDate>00</effectiveDate> <expandedData attr1="case1"> <expandedData attr2="value2"> <data attrD="VD2">value D2</data> </expandedData> <expandedData attr3="value3"> <data attrD="vd3">value D3</data> </expandedData> <expandedData attr4="value4"> <data attrd4="vd4">value d4</data> <name nameattr="specific_name"/> </expandedData> </expandedData> </letterContent>
我使用的Java代码
package org.test.XMLMERGE; import static javax.xml.xpath.XPathConstants.*; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import javax.xml.xpath.*; import org.w3c.dom.*; import org.xml.sax.InputSource; public class Xml2into1 { public static void main(String[] args) throws Exception { // read from files InputSource xml1 = new InputSource("R:/java/dev/tmp/dest.xml"); InputSource xml2 = new InputSource("R:/java/dev/tmp/orig2.xml"); // find the node to add to XPath xpath = XPathFactory.newInstance().newXPath(); Node e1 = (Node) xpath.evaluate("//expandedData[@attr1='case1']", xml1, NODE); Document doc1 = e1.getOwnerDocument(); // insert the nodes Node e2 = (Node) xpath.evaluate("//expandedData[@attr4='value4']", xml2, NODE); e1.appendChild(doc1.adoptNode(e2)); // print results TransformerFactory.newInstance() .newTransformer() .transform(new DOMSource(doc1), new StreamResult(System.out)); } }
实际得到的结果(属性值丢失)
<letterContent> <key1>key1</key1> <key2>key2</key2> <type>456</type> <object1>789</object1> <effectiveDate>00</effectiveDate> <expandedData attr1="case1"> <expandedData attr2="value2"> <data attrD="VD2">value D2</data> </expandedData> <expandedData attr3="value3"> <data attrD="vd3">value D3</data> </expandedData> <expandedData attr4=""> <data attrd4="">value d4</data> <name nameattr=""/> </expandedData> </expandedData> </letterContent>
解决思路与修复方案
这个问题的核心在于你使用的adoptNode()方法。虽然它可以将节点从源文档转移到目标文档,但当两个文档的DOM上下文(比如命名空间、实现细节)不一致时,它可能无法正确保留属性值。更可靠的做法是使用importNode()方法,它会完整复制节点及其所有子节点、属性,并适配到目标文档的环境中。
修改后的代码
只需要修改插入节点的那一行代码,将adoptNode()替换为importNode(),并设置第二个参数为true(表示深度导入,包含所有子节点和属性):
package org.test.XMLMERGE; import static javax.xml.xpath.XPathConstants.*; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import javax.xml.xpath.*; import org.w3c.dom.*; import org.xml.sax.InputSource; public class Xml2into1 { public static void main(String[] args) throws Exception { // read from files InputSource xml1 = new InputSource("R:/java/dev/tmp/dest.xml"); InputSource xml2 = new InputSource("R:/java/dev/tmp/orig2.xml"); // find the node to add to XPath xpath = XPathFactory.newInstance().newXPath(); Node e1 = (Node) xpath.evaluate("//expandedData[@attr1='case1']", xml1, NODE); Document doc1 = e1.getOwnerDocument(); // insert the nodes - 这里是修改的核心 Node e2 = (Node) xpath.evaluate("//expandedData[@attr4='value4']", xml2, NODE); // 使用importNode深度导入节点及所有属性、子节点 Node importedNode = doc1.importNode(e2, true); e1.appendChild(importedNode); // print results TransformerFactory.newInstance() .newTransformer() .transform(new DOMSource(doc1), new StreamResult(System.out)); } }
为什么这样修改有效?
importNode(Node importedNode, boolean deep)方法会创建一个目标文档的副本节点:- 当
deep=true时,会递归导入所有子节点、属性和文本内容 - 它会自动处理源文档和目标文档之间的DOM上下文差异,确保属性值被正确保留
- 当
- 而
adoptNode()只是将节点的所有权转移,不会做上下文适配,这就是导致属性值丢失的原因
修改后运行代码,你就能得到符合预期的XML结果,所有属性值都会被正确保留。
内容的提问来源于stack exchange,提问作者Zamboo
相关产品推荐
相关产品推荐

