Java中如何复制⼀xml⽂件中某⼀节点到另⼀个xml⽂件中,⽽不报错【要插⼊的节点出⾃不。。。
提要:我解析的是word⽂件即docx格式的,⾥的l⽂件,如果你将word⽂件的【.docx】改成【.zip】然后打开 你就明⽩了。xml文件怎么打开
然后呢 去解析其中⼀个word⾥的XML获取指定节点然后放⼊到另外⼀个word⾥的XML(实际你只要解析的是XML,以下⽅法应该都是可⽤的)。
⾸先我使⽤的是W3C的Document(即org.w3c.dom.Document),毕竟我觉得它⾥⾯的查节点和删除插⼊节点是最⽅便的。
⽐如:
//不解压docx⽂件,以ZIP⽅式直接读取
File fileDocx = new File("D:\\DOC\\text.docx");
java.util.zip.ZipFile zipDocxFile = new java.util.zip.ZipFile(fileDocx);
java.util.zip.ZipEntry zipDocumentXML = Entry("l");
InputStream zipDocumentXMLIS = InputStream(zipDocumentXML);
org.w3c.dom.Document zipDocument = wDocumentBuilder().parse(zipDocumentXMLIS);
org.w3c.dom.NodeList BNodeList = ElementsByTagName("wp:docPr");
然后另外⼀个XML的节点的读取⽅式也和上⾯⼀样,
假设现在获取第⼆XML的节点为A,
org.w3c.dom.Element AElement = (org.w3c.dom.Element)ElementsByTagName("m:oMath").item(0);
然后我们获取BNodeList的第⼀个节点
org.w3c.dom.Element BElement = (org.w3c.dom.Element)BNodeList.item(0);
然后我们需要将A节点插⼊到B节点之前,即B的上⼀个兄弟节点的位置
此时不能使⽤
这样⽤肯定会报错【要插⼊的节点出⾃不同的⽂档上下⽂】
我遇到这种情况时,⽹上查询了⼀下 都没有给出⼀个明确的⽅法,有的说⽤importNode,但是它不是w3c的⽅法,⽹上说importNode只能引⼊其他xml的节点,并能指定位置引⼊(笔者没有尝试过,有兴趣的可以尝试验证下哈)
如果⽤w3c的节点clone⽅法,也是会报上⾯的错。
仔细想想就知道,不管是克隆还是什么,都没有改变A节点的 指向对象 是A的Document,要想将A节点插⼊到B的Document对象⾥,就必须先将A的对象变成B的对象,然后再插⼊。
顺着这个思路往下⾛,⽬前笔者想到是⽅法是⽤【递归】的⽅式 在B的Document对象下新建个与A的⼀级节点⼀样的初始节点C,然后⽤节点C(C是指向B的)去复制A节点信息,⽤【递归】的⽅式复制到C节点⾥,最后C节点和A节点⼀模⼀样,只是⼆者的指向对象不同了,然后将C插⼊到B的Document对象⾥,这样就实现了 跨XML 复制节点
实现⽅式如下
//先在B的Document对象下建⽴与A相同的初始节点
Node ANodeCopy = ateElement("m:oMath");
//然后调⽤递归⽅法
recursionElement(ANodeCopy ,zipDocument,AElement);
//递归⽅法实现逻辑为
/**
*
* @Title: recursionElement
* @Description: 递归⽅法,进⾏节点复制
* @param: ANodeCopy ⽬前Document对象下新建的节点
* @param: document  ⽬标Document对象
* @param: AElement  源节点(被复制的节点)
* @return: void
*/
private static void recursionElement(Node ANodeCopy,org.w3c.dom.Document document,org.w3c.dom.Element AElement) {  if(AElement.hasChildNodes()) {
NodeList nodeList = ChildNodes();
for(int i = 0; i < Length(); i++) {
Node itemNode = nodeList.item(i);
String nodename = NodeName();//获取⼦节点名称
org.w3c.dom.Element childNode = ateElement(nodename);
if(itemNode.hasAttributes()) {//赋值属性
//获取当前节点的所有属性,然后循环赋值给新的节点上
NamedNodeMap attribute = Attributes();
for(int j = 0; j < Length(); j++) {
if(StringUtils.isEmpty(attribute.item(j).getTextContent())) {
childNode.setAttribute(attribute.item(j).getNodeName(), "");
}else {
childNode.setAttribute(attribute.item(j).getNodeName(), attribute.item(j).getTextContent());
}
}
}
/*
*  <m:oMath>
*    <m:r>
*    <m:t>B</m:t>
*    </m:r>
*    <m:r m:val="bar">
*    <m:t>=</m:t>
*    </m:r>
</m:oMath>
*  此处的判断是因为,m:t节点是底层,有⽂本内容的节点,
*  itemNode.hasChildNodes()在m:t节点上返回的是true,
*/
if("m:t".equals(nodename)) {
childNode.TextContent());
}
ANodeCopy.appendChild(childNode);
if(!"m:t".equals(nodename) && itemNode.hasChildNodes()) {
recursionElement(childNode,document,(org.w3c.dom.Element) itemNode);
}
}
}
}
不同的节点递归赋值存在差异,此处仅提供⼀个思路