fix(测试跟踪): 导入xmind支持 自由主题风格/支持多画布

This commit is contained in:
fit2-zhao 2020-09-30 11:14:01 +08:00
parent 1c7ce5e20b
commit 8ba24261b6
4 changed files with 188 additions and 157 deletions

View File

@ -270,25 +270,34 @@ public class XmindCaseParser {
StringBuffer processBuffer = new StringBuffer();
try {
// 获取思维导图内容
JsonRootBean root = XmindParser.parseObject(multipartFile);
if (root != null && root.getRootTopic() != null && root.getRootTopic().getChildren() != null) {
// 判断是模块还是用例
for (Attached item : root.getRootTopic().getChildren().getAttached()) {
if (isAvailable(item.getTitle(), "(?:tc:|tc|tc)")) { // 用例
return replace(item.getTitle(), "(?:tc:|tc|tc)") + "" + Translator.get("test_case_create_module_fail");
} else {
item.setPath(item.getTitle());
if (item.getChildren() != null && !item.getChildren().getAttached().isEmpty()) {
recursion(processBuffer, item, 1, item.getChildren().getAttached());
List<JsonRootBean> roots = XmindParser.parseObject(multipartFile);
for (JsonRootBean root : roots) {
if (root != null && root.getRootTopic() != null && root.getRootTopic().getChildren() != null) {
// 判断是模块还是用例
for (Attached item : root.getRootTopic().getChildren().getAttached()) {
if (isAvailable(item.getTitle(), "(?:tc:|tc|tc)")) { // 用例
return replace(item.getTitle(), "(?:tc:|tc|tc)") + "" + Translator.get("test_case_create_module_fail");
} else {
String nodePath = item.getTitle();
item.setPath(nodePath);
if (item.getChildren() != null && !item.getChildren().getAttached().isEmpty()) {
recursion(processBuffer, item, 1, item.getChildren().getAttached());
} else {
if (!nodePath.startsWith("/")) {
nodePath = "/" + nodePath;
}
if (nodePath.endsWith("/")) {
nodePath = nodePath.substring(0, nodePath.length() - 1);
}
nodePaths.add(nodePath); // 没有用例的路径
}
}
}
}
}
this.validate();
} catch (Exception ex) {
processBuffer.append(Translator.get("incorrect_format"));
LogUtil.error(ex.getMessage());
return "xmind "+Translator.get("incorrect_format");
return ex.getMessage();
}
return process.toString();
}

View File

@ -5,75 +5,83 @@ import org.json.JSONObject;
import org.json.XML;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class XmindLegacy {
/**
* 返回content.xml和comments.xml合并后的json
*
* @param xmlContent
* @param xmlComments
* @return
* @throws IOException
* @throws DocumentException
*/
public static String getContent(String xmlContent, String xmlComments) throws IOException, DocumentException {
// 删除content.xml里面不能识别的字符串
xmlContent = xmlContent.replace("xmlns=\"urn:xmind:xmap:xmlns:content:2.0\"", "");
xmlContent = xmlContent.replace("xmlns:fo=\"http://www.w3.org/1999/XSL/Format\"", "");
// 删除<topic>节点
xmlContent = xmlContent.replace("<topics type=\"attached\">", "");
xmlContent = xmlContent.replace("</topics>", "");
/**
* 返回content.xml和comments.xml合并后的json
*
* @param xmlContent
* @param xmlComments
* @return
* @throws IOException
* @throws DocumentException
*/
public static List<String> getContent(String xmlContent, String xmlComments) throws IOException, DocumentException {
// 删除content.xml里面不能识别的字符串
xmlContent = xmlContent.replace("xmlns=\"urn:xmind:xmap:xmlns:content:2.0\"", "");
xmlContent = xmlContent.replace("xmlns:fo=\"http://www.w3.org/1999/XSL/Format\"", "");
// 删除<topic>节点
xmlContent = xmlContent.replace("<topics type=\"attached\">", "");
xmlContent = xmlContent.replace("</topics>", "");
// 去除title中svg:width属性
xmlContent = xmlContent.replaceAll("<title svg:width=\"[0-9]*\">", "<title>");
// 去除title中svg:width属性
xmlContent = xmlContent.replaceAll("<title svg:width=\"[0-9]*\">", "<title>");
//去除自由风格主题
xmlContent = xmlContent.replaceAll("<topics type=\"detached\">", "");
Document document = DocumentHelper.parseText(xmlContent);// 读取XML文件,获得document对象
Element root = document.getRootElement();
List<Node> topics = root.selectNodes("//topic");
Document document = DocumentHelper.parseText(xmlContent);// 读取XML文件,获得document对象
Element root = document.getRootElement();
List<Node> topics = root.selectNodes("//topic");
if (xmlComments != null) {
// 删除comments.xml里面不能识别的字符串
xmlComments = xmlComments.replace("xmlns=\"urn:xmind:xmap:xmlns:comments:2.0\"", "");
if (xmlComments != null) {
// 删除comments.xml里面不能识别的字符串
xmlComments = xmlComments.replace("xmlns=\"urn:xmind:xmap:xmlns:comments:2.0\"", "");
// 添加评论到content中
Document commentDocument = DocumentHelper.parseText(xmlComments);
List<Node> commentsList = commentDocument.selectNodes("//comment");
// 添加评论到content中
Document commentDocument = DocumentHelper.parseText(xmlComments);
List<Node> commentsList = commentDocument.selectNodes("//comment");
for (Node topic : topics) {
for (Node commentNode : commentsList) {
Element commentElement = (Element) commentNode;
Element topicElement = (Element) topic;
if (topicElement.attribute("id").getValue()
.equals(commentElement.attribute("object-id").getValue())) {
Element comment = topicElement.addElement("comments");
comment.addAttribute("creationTime", commentElement.attribute("time").getValue());
comment.addAttribute("author", commentElement.attribute("author").getValue());
comment.addAttribute("content", commentElement.element("content").getText());
}
}
for (Node topic : topics) {
for (Node commentNode : commentsList) {
Element commentElement = (Element) commentNode;
Element topicElement = (Element) topic;
if (topicElement.attribute("id").getValue()
.equals(commentElement.attribute("object-id").getValue())) {
Element comment = topicElement.addElement("comments");
comment.addAttribute("creationTime", commentElement.attribute("time").getValue());
comment.addAttribute("author", commentElement.attribute("author").getValue());
comment.addAttribute("content", commentElement.element("content").getText());
}
}
}
}
}
}
// 第一个topic转换为json中的rootTopic
Node rootTopic = root.selectSingleNode("/xmap-content/sheet/topic");
rootTopic.setName("rootTopic");
// 第一个topic转换为json中的rootTopic
List<Node> rootTopics = root.selectNodes("/xmap-content/sheet/topic");
for (Node rootTopic : rootTopics) {
rootTopic.setName("rootTopic");
// 将xml中topic节点转换为attached节点
List<Node> topicList = rootTopic.selectNodes("//topic");
// 将xml中topic节点转换为attached节点
List<Node> topicList = rootTopic.selectNodes("//topic");
for (Node node : topicList) {
node.setName("attached");
}
for (Node node : topicList) {
node.setName("attached");
}
// 选取第一个sheet
Element sheet = root.elements("sheet").get(0);
String res = sheet.asXML();
// 将xml转为json
JSONObject xmlJSONObj = XML.toJSONObject(res);
JSONObject jsonObject = xmlJSONObj.getJSONObject("sheet");
// 设置缩进
return jsonObject.toString(4);
}
}
List<String> sheets = new ArrayList<>();
for (Element sheet : root.elements("sheet")) {
String res = sheet.asXML();
// 将xml转为json
JSONObject xmlJSONObj = XML.toJSONObject(res);
JSONObject jsonObject = xmlJSONObj.getJSONObject("sheet");
sheets.add(jsonObject.toString(4));
}
// 设置缩进
return sheets;
}
}

View File

@ -34,61 +34,68 @@ public class XmindParser {
* @throws ArchiveException
* @throws DocumentException
*/
public static String parseJson(MultipartFile multipartFile) throws IOException, ArchiveException, DocumentException {
public static List<String> parseJson(MultipartFile multipartFile) throws IOException, ArchiveException, DocumentException {
File file = FileUtil.multipartFileToFile(multipartFile);
List<String> contents = null;
String res = null;
if (file == null || !file.exists())
MSException.throwException(Translator.get("incorrect_format"));
String res = ZipUtils.extract(file);
String content = null;
if (isXmindZen(res, file)) {
content = getXmindZenContent(file, res);
} else {
content = getXmindLegacyContent(file, res);
try {
res = ZipUtils.extract(file);
if (isXmindZen(res, file)) {
contents = (getXmindZenContent(file, res));
} else {
contents = getXmindLegacyContent(file, res);
}
} catch (Exception e) {
MSException.throwException(e.getMessage());
} finally {
// 删除生成的文件夹
if (res != null) {
File dir = new File(res);
FileUtil.deleteDir(dir);
}
// 删除零时文件
if (file != null)
file.delete();
}
// 删除生成的文件夹
File dir = new File(res);
FileUtil.deleteDir(dir);
JsonRootBean jsonRootBean = JSON.parseObject(content, JsonRootBean.class);
// 删除零时文件
if (file != null)
file.delete();
String json = (JSON.toJSONString(jsonRootBean, false));
if (StringUtils.isEmpty(content) || content.split("(?:tc:|tc|TC:|TC|tc|TC)").length == 1) {
MSException.throwException(Translator.get("import_xmind_not_found"));
}
if (!StringUtils.isEmpty(content) && content.split("(?:tc:|tc|TC:|TC|tc|TC)").length > 500) {
MSException.throwException(Translator.get("import_xmind_count_error"));
}
return json;
return contents;
}
public static JsonRootBean parseObject(MultipartFile multipartFile) throws DocumentException, ArchiveException, IOException {
String content = parseJson(multipartFile);
JsonRootBean jsonRootBean = JSON.parseObject(content, JsonRootBean.class);
return jsonRootBean;
public static List<JsonRootBean> parseObject(MultipartFile multipartFile) throws DocumentException, ArchiveException, IOException {
List<String> contents = parseJson(multipartFile);
int caseCount = 0;
List<JsonRootBean> jsonRootBeans = new ArrayList<>();
if (contents != null) {
for (String content : contents) {
caseCount += content.split("(?:tc:|tc|TC:|TC|tc|TC)").length;
JsonRootBean jsonRootBean = JSON.parseObject(content, JsonRootBean.class);
jsonRootBeans.add(jsonRootBean);
}
if (caseCount > 500) {
MSException.throwException(Translator.get("import_xmind_count_error"));
}
}
return jsonRootBeans;
}
/**
* @return
*/
public static String getXmindZenContent(File file, String extractFileDir)
public static List<String> getXmindZenContent(File file, String extractFileDir)
throws IOException, ArchiveException {
List<String> keys = new ArrayList<>();
keys.add(xmindZenJson);
Map<String, String> map = ZipUtils.getContents(keys, file, extractFileDir);
String content = map.get(xmindZenJson);
content = XmindZen.getContent(content);
return content;
return XmindZen.getContent(content);
}
/**
* @return
*/
public static String getXmindLegacyContent(File file, String extractFileDir)
public static List<String> getXmindLegacyContent(File file, String extractFileDir)
throws IOException, ArchiveException, DocumentException {
List<String> keys = new ArrayList<>();
keys.add(xmindLegacyContent);
@ -97,7 +104,7 @@ public class XmindParser {
String contentXml = map.get(xmindLegacyContent);
String commentsXml = map.get(xmindLegacyComments);
String xmlContent = XmindLegacy.getContent(contentXml, commentsXml);
List<String> xmlContent = XmindLegacy.getContent(contentXml, commentsXml);
return xmlContent;
}

View File

@ -5,61 +5,68 @@ import com.alibaba.fastjson.JSONObject;
import org.dom4j.DocumentException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class XmindZen {
/**
* @param jsonContent
* @return
* @throws IOException
* @throws DocumentException
*/
public static String getContent(String jsonContent) {
JSONObject jsonObject = JSONArray.parseArray(jsonContent).getJSONObject(0);
JSONObject rootTopic = jsonObject.getJSONObject("rootTopic");
transferNotes(rootTopic);
JSONObject children = rootTopic.getJSONObject("children");
recursionChildren(children);
return jsonObject.toString();
}
/**
* @param jsonContent
* @return
* @throws IOException
* @throws DocumentException
*/
public static List<String> getContent(String jsonContent) {
JSONArray jsonArray = JSONArray.parseArray(jsonContent);//.getJSONObject(0);
List<String> contents = new ArrayList<>();
for (int i = 0; i < jsonArray.size(); i++) {
JSONObject jsonObject = (JSONObject) jsonArray.get(i);
JSONObject rootTopic = jsonObject.getJSONObject("rootTopic");
transferNotes(rootTopic);
JSONObject children = rootTopic.getJSONObject("children");
recursionChildren(children);
contents.add(jsonObject.toString());
}
return contents;
}
/**
* 递归转换children
*
* @param children
*/
private static void recursionChildren(JSONObject children) {
if (children == null) {
return;
}
JSONArray attachedArray = children.getJSONArray("attached");
if (attachedArray == null) {
return;
}
for (Object attached : attachedArray) {
JSONObject attachedObject = (JSONObject) attached;
transferNotes(attachedObject);
JSONObject childrenObject = attachedObject.getJSONObject("children");
if (childrenObject == null) {
continue;
}
recursionChildren(childrenObject);
}
}
/**
* 递归转换children
*
* @param children
*/
private static void recursionChildren(JSONObject children) {
if (children == null) {
return;
}
JSONArray attachedArray = children.getJSONArray("attached");
if (attachedArray == null) {
return;
}
for (Object attached : attachedArray) {
JSONObject attachedObject = (JSONObject) attached;
transferNotes(attachedObject);
JSONObject childrenObject = attachedObject.getJSONObject("children");
if (childrenObject == null) {
continue;
}
recursionChildren(childrenObject);
}
}
private static void transferNotes(JSONObject object) {
JSONObject notes = object.getJSONObject("notes");
if (notes == null) {
return;
}
JSONObject plain = notes.getJSONObject("plain");
if (plain != null) {
String content = plain.getString("content");
notes.remove("plain");
notes.put("content", content);
} else {
notes.put("content", null);
}
}
private static void transferNotes(JSONObject object) {
JSONObject notes = object.getJSONObject("notes");
if (notes == null) {
return;
}
JSONObject plain = notes.getJSONObject("plain");
if (plain != null) {
String content = plain.getString("content");
notes.remove("plain");
notes.put("content", content);
} else {
notes.put("content", null);
}
}
}