对应XMind的读入,注释写的挺详细了,不懂评论即可,作者常年蹲在csdn。现在的utils兼容XMind8和ProcessOn下载的XMind。目前在写XMind的jar包
pom.xml:
<!--Xmind -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.20</version>
</dependency>
<dependency>
<groupId>com.github.eljah</groupId>
<artifactId>xmindjbehaveplugin</artifactId>
<version>0.8</version>
</dependency>
model:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class XMindNodeModel implements Serializable {
String content;
String comment;
Set<String> labels;
Set<String> markers;
String link;
Integer level;
String iImage;
List<XMindNodeModel> children;
public enum ColumnEnum{
content,
comment,
labels,
markers,
link,
level,
iImage;
}
}
utils:
@Slf4j
public class MyXMindUtils {
public static final String CONTENT_JSON = "content.json";
//当前文件位置
private static final String CURRENT_PATH = System.getProperty("user.dir");
/**
* 想读XMind,读就完了
* */
public static Object readXMind(File file) {
String res = null;
Object contents = null;
try {
res = extract(file);
if (isXMindNetwork(res, file)) {
contents = (getXMindNetworkContent(file, res));
} else {
contents = getXMind8Content(file);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 删除生成的文件夹
if (res != null) {
File dir = new File(res);
deleteDir(dir);
}
// 删除零时文件
// if (file != null) {
// file.delete();
// }
}
return contents;
}
/**
* 填充节点
*
* @param iTopic
* @return 一个节点
*/
public static XMindNodeModel fillNode(ITopic iTopic) {
XMindNodeModel newNode = new XMindNodeModel();
try {
//内容
newNode.setContent(iTopic.getTitleText());
//链接
newNode.setLink(iTopic.getHyperlink());
//标签
Set<String> labels = iTopic.getLabels();
if (labels != null && labels.size() != 0) {
newNode.setLabels(labels);
}
//图片
//IImage image = iTopic.getImage();
//newNode.setIImage(image.getSource());
//批注
//newNode.setMarkers();
//备注
IPlainNotesContent content = (IPlainNotesContent) iTopic.getNotes().getContent(INotes.PLAIN);
if (content != null) {
newNode.setComment(content.getTextContent());
}
} catch (Exception e) {
log.error("*****填充node出错*****");
e.printStackTrace();
}
return newNode;
}
/**
* 填充节点
*
* @param attachedObject
* @return 一个节点
*/
public static XMindNodeModel fillNodeNetwork(JSONObject attachedObject) {
XMindNodeModel newNode = new XMindNodeModel();
try {
JSONObject notes = attachedObject.getJSONObject("notes");
if (notes != null) {
JSONObject plain = notes.getJSONObject("plain");
if (plain != null) {
newNode.setComment(plain.getString("content"));
}
}
newNode.setContent(attachedObject.getString("title"));
newNode.setLabels(Collections.singleton(attachedObject.getString("labels")));
newNode.setMarkers(Collections.singleton(attachedObject.getString("markers")));
} catch (Exception e) {
log.error("*****填充nodeNetwork出错*****");
e.printStackTrace();
}
return newNode;
}
/**
* 建立文件内容树
*
* @param file
* @return json串
*/
public static Object getXMind8Content(File file) {
//初始化builder
IWorkbookBuilder builder = Core.getWorkbookBuilder();
IWorkbook workbook = null;
try {
//打开XMind文件
workbook = builder.loadFromFile(file, new ByteArrayStorage(), null);
} catch (IOException | CoreException e) {
e.printStackTrace();
}
if (workbook==null){
return "文件为空或格式不匹配";
}
//获取主Sheet
ISheet defSheet = workbook.getPrimarySheet();
//获取根Topic
ITopic rootTopic = defSheet.getRootTopic();
//遍历树
Queue<Object> iTopicQueue = new LinkedList<>();
iTopicQueue.add(rootTopic);
//新树
XMindNodeModel xMindNodeRoot = new XMindNodeModel();
xMindNodeRoot.setContent(rootTopic.getTitleText());
xMindNodeRoot.setLevel(1);
iTopicQueue.add(xMindNodeRoot);
while (!iTopicQueue.isEmpty()) {
ITopic oldTreeNode = (ITopic) iTopicQueue.poll();
XMindNodeModel treeNode = (XMindNodeModel) iTopicQueue.poll();
if (treeNode == null) {
return null;
}
Integer level = treeNode.getLevel() + 1;
List<XMindNodeModel> xMindNodeModels = new ArrayList<>();
for (ITopic oneChild: oldTreeNode.getAllChildren()) {
XMindNodeModel newNode = MyXMindUtils.fillNode(oneChild);
newNode.setLevel(level);
xMindNodeModels.add(newNode);
iTopicQueue.add(oneChild);
iTopicQueue.add(newNode);
}
treeNode.setChildren(xMindNodeModels);
}
return JSON.toJSON(xMindNodeRoot);
}
/**
* 网上版本 建立文件内容树
*
* @param file
* @return json串
*/
public static Object getXMindNetworkContent(File file, String extractFileDir)
throws IOException {
List<String> keys = new ArrayList<>();
keys.add(CONTENT_JSON);
Map<String, String> map = getContents(keys, file, extractFileDir);
String content = map.get(CONTENT_JSON);
JSONArray jsonArray = JSONArray.parseArray(content);
JSONObject jsonObject = (JSONObject) jsonArray.get(0);
JSONObject rootTopic = jsonObject.getJSONObject("rootTopic");
//遍历树
Queue<Object> iTopicQueue = new LinkedList<>();
iTopicQueue.add(rootTopic);
//新树
XMindNodeModel xMindNodeRoot = new XMindNodeModel();
xMindNodeRoot.setContent(rootTopic.getString("title"));
xMindNodeRoot.setLevel(1);
iTopicQueue.add(xMindNodeRoot);
while(!iTopicQueue.isEmpty()){
JSONObject oldTreeNode = (JSONObject) iTopicQueue.poll();
XMindNodeModel treeNode = (XMindNodeModel) iTopicQueue.poll();
if (treeNode == null) {
return null;
}
Integer level = treeNode.getLevel() + 1;
List<XMindNodeModel> xMindNodeModels = new ArrayList<>();
JSONObject children = oldTreeNode.getJSONObject("children");
if(children == null){
continue;
}
JSONArray attachedArray = children.getJSONArray("attached");
if (attachedArray == null) {
continue;
}
for (Object attached : attachedArray) {
JSONObject attachedObject = (JSONObject) attached;
XMindNodeModel newNode = MyXMindUtils.fillNodeNetwork(attachedObject);
newNode.setLevel(level);
xMindNodeModels.add(newNode);
iTopicQueue.add(attachedObject);
iTopicQueue.add(newNode);
}
treeNode.setChildren(xMindNodeModels);
}
return JSON.toJSON(xMindNodeRoot);
}
/**
*判断是否有CONTENT_JSON文件
*
* */
private static boolean isXMindNetwork(String res, File file) {
// 解压
File parent = new File(res);
if (parent.isDirectory()) {
String[] files = parent.list(new FileFilter());
for (int i = 0; i < Objects.requireNonNull(files).length; i++) {
if (files[i].equals(CONTENT_JSON)) {
return true;
}
}
}
return false;
}
/**
* 返回解压后的文件夹名字
*
*/
public static String extract(File file) throws IOException, ArchiveException {
Expander expander = new Expander();
String destFileName = CURRENT_PATH + File.separator + "XMind" + System.currentTimeMillis();
expander.expand(file, new File(destFileName));
return destFileName;
}
/**
* 找CONTENT_JSON文件
*
* */
public static Map<String, String> getContents(List<String> subFileNames, File file, String extractFileDir)
throws IOException {
String destFilePath = extractFileDir;
Map<String, String> map = new HashMap<>(16);
File destFile = new File(destFilePath);
if (destFile.isDirectory()) {
String[] res = destFile.list(new FileFilter());
for (int i = 0; i < Objects.requireNonNull(res).length; i++) {
if (subFileNames.contains(res[i])) {
String s = destFilePath + File.separator + res[i];
String content = getFileContent(s);
map.put(res[i], content);
}
}
}
return map;
}
/**
* 返回CONTENT_JSON文件内容
*
* */
public static String getFileContent(String fileName) throws IOException {
File file;
try {
file = new File(fileName);
} catch (Exception e) {
throw new RuntimeException("找不到该文件");
}
FileReader fileReader = new FileReader(file);
BufferedReader bufferedReder = new BufferedReader(fileReader);
StringBuilder stringBuffer = new StringBuilder();
while (bufferedReder.ready()) {
stringBuffer.append(bufferedReder.readLine());
}
// 打开的文件需关闭,在unix下可以删除,否则在windows下不能删除(file.delete())
bufferedReder.close();
fileReader.close();
return stringBuffer.toString();
}
/**
* 过滤器
*/
static class FileFilter implements FilenameFilter {
@Override
public boolean accept(File dir, String name) {
// String的 endsWith(String str)方法 筛选出以str结尾的字符串
if (name.endsWith(".xml") || name.endsWith(".json")) {
return true;
}
return false;
}
}
/**
* 删除生成的文件夹
*/
public static boolean deleteDir(File dir) {
if (dir.isDirectory()) {
String[] children = dir.list();
// 递归删除目录中的子目录下
for (int i = 0; i < children.length; i++) {
boolean success = deleteDir(new File(dir, children[i]));
if (!success) {
return false;
}
}
}
// 目录此时为空,可以删除
return dir.delete();
}
}
使用方式:
@SpringBootTest
public class XmindTests {
@Test
public void Xmind() {
File file = new File("C:\\Users\\Desktop\\xxx.xmind");
System.out.println(MyXMindUtils.readXMind(file));
}
}