diff --git a/backend/src/main/java/io/metersphere/xmind/XmindCaseParser.java b/backend/src/main/java/io/metersphere/xmind/XmindCaseParser.java index b6b864170a..2585b37376 100644 --- a/backend/src/main/java/io/metersphere/xmind/XmindCaseParser.java +++ b/backend/src/main/java/io/metersphere/xmind/XmindCaseParser.java @@ -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 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(); } diff --git a/backend/src/main/java/io/metersphere/xmind/parser/XmindLegacy.java b/backend/src/main/java/io/metersphere/xmind/parser/XmindLegacy.java index 1a6ae73728..55c17cc6d3 100644 --- a/backend/src/main/java/io/metersphere/xmind/parser/XmindLegacy.java +++ b/backend/src/main/java/io/metersphere/xmind/parser/XmindLegacy.java @@ -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\"", ""); - // 删除节点 - xmlContent = xmlContent.replace("", ""); - xmlContent = xmlContent.replace("", ""); + /** + * 返回content.xml和comments.xml合并后的json + * + * @param xmlContent + * @param xmlComments + * @return + * @throws IOException + * @throws DocumentException + */ + public static List 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\"", ""); + // 删除节点 + xmlContent = xmlContent.replace("", ""); + xmlContent = xmlContent.replace("", ""); - // 去除title中svg:width属性 - xmlContent = xmlContent.replaceAll("", "<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; + } } diff --git a/backend/src/main/java/io/metersphere/xmind/parser/XmindParser.java b/backend/src/main/java/io/metersphere/xmind/parser/XmindParser.java index d61a28a9d7..2d7ef83919 100644 --- a/backend/src/main/java/io/metersphere/xmind/parser/XmindParser.java +++ b/backend/src/main/java/io/metersphere/xmind/parser/XmindParser.java @@ -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; } diff --git a/backend/src/main/java/io/metersphere/xmind/parser/XmindZen.java b/backend/src/main/java/io/metersphere/xmind/parser/XmindZen.java index 6ba9d2021b..4de22142be 100644 --- a/backend/src/main/java/io/metersphere/xmind/parser/XmindZen.java +++ b/backend/src/main/java/io/metersphere/xmind/parser/XmindZen.java @@ -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); + } + } }