根据传入的xpath生成对应的xml文件
国内网站上这一块可以参考的东西很少,所有自己写了一个工具类,不需要导入额外的jar包,给大家分享一下
输入文件:
input.txt
Student/PlayGame
Student/FallInLove
Student/WatchTV
Student/Games/LOL
Student/Games/CF
Student/Games/DNF
Student/Lovers/Jack
Student/Lovers/Daniel
Student/Lovers/Lily
Student/Money/dollar
Student/Money/RMB
Student/Vehicle/BMW
代码:
package com.blog;
import java.io.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.*;
/**
* @Author Daniel
* @Description 自制工具类:给定Xpath生成XML文件
**/
public class XMLUtils {
static final String NODENAME_SEP = "/";
public static void main(String[] args) throws Exception {
File inputFile = new File("input.txt");
File outputFile = new File("output.xml");
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(inputFile));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(outputFile));
byte[] bu = new byte[1024 * 1024 * 8];
int len;
//将给定的Xpath结合成一个大的字符串
StringBuilder xpaths = new StringBuilder();
while ((len = bis.read(bu)) != -1) {
xpaths.append(new String(bu, 0, len));
}
String rootName = xpaths.substring(0, xpaths.indexOf("/"));
String xml = createXML(rootName, xpaths.toString());
bos.write(xml.getBytes());
bos.close();
bis.close();
System.out.println("finished");
}
//创建XML字符串
public static String createXML(String rootName, String xpaths) {
Document doc = createDocument(rootName, null);
Element root = doc.getDocumentElement();
//按行切割字符串
String[] split = xpaths.split("\r\n");
for (String s : split) {
//replaceFirst用来删除root节点的名字
createNode(doc, root, s.replaceFirst(rootName + "/", ""), "somevalue");
}
return getResult(doc);
}
//初始化Document对象
public static Document createDocument(String name, String namespace) {
//前置操作
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = null;
try {
db = dbf.newDocumentBuilder();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
DOMImplementation impl = db.getDOMImplementation();
//必须使用DOMImplementation类中的createDocument方法来创建root节点
Document doc = impl.createDocument(namespace, name, null);
return doc;
}
//创建所有节点
public static void createNode(Document doc, Node parentNode, String childName, String text) {
String[] childNames = childName.split(NODENAME_SEP);
String childNodeName = childNames[0];
//获取到子节点
Node childNode = getChildByName(parentNode, childNodeName);
// Node childNode = ((Element) parentNode).getElementsByTagName(childNodeName).item(0);//这种写法错误,如果出现同名则会有问题
//不为空说明已经创建过父级节点,然后创建子级节点
if (childNode != null) {
//长度大于1才有子级节点
if (childNames.length > 1) {
StringBuilder str = new StringBuilder();
for (int i = 1; i < childNames.length; i++) {
str.append(childNames[i] + NODENAME_SEP);
}
//递归创建
createNode(doc, childNode, str.toString(), text);
return;
}
}
childNode = doc.createElement(childNodeName);
//由于前面将childNames中的第一个元素作为判断Node是否为空的条件,如果这个节点的上一级不为root的话无法将其添加上去,这段代码就是用来解决这个问题
if (childNames.length > 1) {
//同上面逻辑
StringBuilder str = new StringBuilder();
for (int i = 1; i < childNames.length; i++) {
str.append(childNames[i] + NODENAME_SEP);
}
//与上面不同的是这里要添加节点
parentNode.appendChild(childNode);
createNode(doc, childNode, str.toString(), text);
return;
}
childNode.setTextContent(text);
parentNode.appendChild(childNode);
}
//输出XML
public static String getResult(Document xml) {
Transformer tf = null;
try {
tf = TransformerFactory.newInstance().newTransformer();
} catch (TransformerConfigurationException e) {
e.printStackTrace();
}
tf.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
Writer out = new StringWriter();
try {
tf.transform(new DOMSource(xml), new StreamResult(out));
} catch (TransformerException e) {
e.printStackTrace();
}
return out.toString().substring(out.toString().indexOf(">") + 1);
}
public static Node getChildByName(Node parentNode, String childName) {
//获取当前node下的所有子节点
NodeList list = parentNode.getChildNodes();
String nodeName;
//遍历子节点,找出子节点中与形参childName值相同的节点
for (int i = 0; i < list.getLength(); i++) {
nodeName = list.item(i).getNodeName();
if (nodeName.equals(childName))
return list.item(i);
}
//如果没有子节点则返回空值
return null;
}
}
输出结果:
output.xml
<Student><PlayGame>somevalue</PlayGame><FallInLove>somevalue</FallInLove><WatchTV>somevalue</WatchTV><Games><LOL>somevalue</LOL><CF>somevalue</CF><DNF>somevalue</DNF></Games><Lovers><Jack>somevalue</Jack><Daniel>somevalue</Daniel><Lily>somevalue</Lily></Lovers><Money><dollar>somevalue</dollar><RMB>somevalue</RMB></Money><Vehicle><BMW>somevalue</BMW></Vehicle></Student>