前言:
将一个大的xml文件分割成若干个小的xml文件,同事使用python实现过,最近学习java,以此练手使用java的jaxp包实现该功能!
说明:
xml文件(如下)中datas节点的子节点data有若干个,当超出100个的时候,就需要以data节点分割成若干份小的xml文件
<?xml version="1.0" encoding="utf-8" ?>
<root>
<head>....</head>
<datas>
<data>...</data>
<data>...</data>
<data>...</data>
...
<!--若干个data节点-->
</datas>
</root>
思路:
1.获取datas节点的子节点data集合;
2.复制该data节点集合(没有找到相关的复制方法,这里通过遍历data集合将data元素存储到ArrayLisrt中);
3.判断data集合长度,若超过了阈值,则进行分割;
4.每次分割前都需要清除datas节点,并重新创建创建,保证分割的数据准确性;
5.保存分割的xml文件
分割xml的代码(核心):
//分割文件:当data大于100的时候,将其分割成data小于100的xml
public static void splitXML(Document document, ArrayList<Node> copyNodeList) {
// 添加data节点到datas节点下
int nodesLen = copyNodeList.size();
// 分割的组数:计算可以分成多少组
int splitTimes = (int) Math.ceil((double) nodesLen / splitSize);
if (nodesLen >= splitSize) {
// 外层循环:控制文件分割的次数
for (int i = 0; i < splitTimes; i++) {
// 获取datas节点
Node datasNode = document.getElementsByTagName("datas").item(0);
// 获取datas节点的父节点
Node parentDatasNode = datasNode.getParentNode();
// 清空datas节点,这样就清空了datas节点的所有内容
parentDatasNode.removeChild(datasNode);
// 创建datas节点
Element newDatasNode = document.createElement("datas");
// 开始位置
int fromIndex = i * splitSize;
// 结束位置:通过三目运算符获取结束值
int toIndex = (i + 1) * splitSize < nodesLen ? (i + 1) * splitSize : nodesLen;
System.out.println("fromIndex:" + fromIndex + ":toIndex:" + toIndex);
for (int j = fromIndex; j < toIndex; j++) {
newDatasNode.appendChild(copyNodeList.get(j));
}
// 添加datas节点到父节点上
parentDatasNode.appendChild(newDatasNode);
// 文件的回写
writeXML(document, saveXmlFolder);
}
}
}
完整代码:
/*
使用jaxp操作xml文件
*/
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import java.io.*;
import java.util.ArrayList;
import java.util.UUID;
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;
public class SplitXMLFile {
// 文件分割的大小
private static int splitSize = 100;
private static String xmlFolder = "src_xml_path.xml";
private static String saveXmlFolder = "split.xml";
public static void main(String[] args) throws Exception {
// 获取根节点
Document nodeRoot = getRootNode();
//通过根节点,获取data节点集合,并复制
ArrayList<Node> copyNodeList = getDataList(nodeRoot);
// 分割文件:大文件分割为小文件
splitXML(nodeRoot, copyNodeList);
}
// 复制datas节点,为了拿到data数据集合
public static ArrayList<Node> copyDataList(NodeList nodeList) {
ArrayList<Node> arrayList = new ArrayList<>();
for (int i = 0; i < nodeList.getLength(); i++) {
arrayList.add(nodeList.item(i));
}
return arrayList;
}
//分割文件:当data大于100的时候,将其分割成data小于100的xml
public static void splitXML(Document document, ArrayList<Node> copyNodeList) {
// 添加data节点到datas节点下
int nodesLen = copyNodeList.size();
// 分割的组数:计算可以分成多少组
int splitTimes = (int) Math.ceil((double) nodesLen / splitSize);
if (nodesLen >= splitSize) {
// 外层循环:控制文件分割的次数
for (int i = 0; i < splitTimes; i++) {
// 获取datas节点
Node datasNode = document.getElementsByTagName("datas").item(0);
// 获取datas节点的父节点
Node parentDatasNode = datasNode.getParentNode();
// 清空datas节点,这样就清空了datas节点的所有内容
parentDatasNode.removeChild(datasNode);
// 创建datas节点
Element newDatasNode = document.createElement("datas");
// 开始位置
int fromIndex = i * splitSize;
// 结束位置:通过三目运算符获取结束值
int toIndex = (i + 1) * splitSize < nodesLen ? (i + 1) * splitSize : nodesLen;
System.out.println("fromIndex:" + fromIndex + ":toIndex:" + toIndex);
for (int j = fromIndex; j < toIndex; j++) {
newDatasNode.appendChild(copyNodeList.get(j));
}
// 添加datas节点到父节点上
parentDatasNode.appendChild(newDatasNode);
// 文件的回写
writeXML(document, saveXmlFolder);
}
}
}
//回写添加的节点文件
public static void writeXML(Node document, String xmlPath) {
String[] pathLst = xmlPath.split("\\.");
StringBuffer sb = new StringBuffer();
sb.append(pathLst[0]).append("_" + UUID.randomUUID()).append("." + pathLst[1]);
// 分割为小文件的xml文件路径
String splitXmlPath = sb.toString();
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer;
try {
transformer = transformerFactory.newTransformer();
transformer.transform(new DOMSource(document), new StreamResult(splitXmlPath));
} catch (Exception e) {
e.printStackTrace();
}
try {
// 读取数据
StringBuffer splitXmlSb = new StringBuffer();
BufferedReader br = new BufferedReader(new FileReader(splitXmlPath));
String line;
while ((line = br.readLine()) != null) {
splitXmlSb.append(line);
}
br.close();
//写入数据
BufferedWriter bw = new BufferedWriter(new FileWriter(splitXmlPath));
String xmlContent = splitXmlSb.toString().replaceAll("\r|\n", "");
bw.write(xmlContent);
bw.newLine();
bw.flush();
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// 获取节点的data数据集合
public static ArrayList<Node> getDataList(Document document) {
NodeList nodeList = document.getElementsByTagName("data");
//复制datas节点,为了拿到data数据集合
return copyDataList(nodeList);
}
// 获取xml文件的根节点
public static Document getRootNode() throws Exception {
//创建解析器工厂
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
//创建解析器
DocumentBuilder builder = builderFactory.newDocumentBuilder();
// 解析:得到文档对象
Document document = builder.parse(xmlFolder);
return document;
}
}