前言
之前在第二篇文章中详细阐述了如何将mxGraph画布上的内容保存到数据库,那么这篇就记录下后台如何将数据库中的xml文件解析出来,然后进行后台处理。
xml样例
<mxGraphModel>
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="2" value="初始化百度网页" style="nodeStyle;image=/img/start.f26db4f5.png" parent="1" vertex="1">
<mxGeometry x="220" y="80" width="130" height="35" as="geometry" />
<Object name="开始" icon="/img/start.f26db4f5.png" nodeName="start" fullPath="" context="https://www.baidu.com/" operation="" as="data" />
</mxCell>
<mxCell id="3" value="输入搜索内容" style="nodeStyle;image=/img/text.ab22920f.png" parent="1" vertex="1">
<mxGeometry x="220" y="170" width="130" height="35" as="geometry" />
<Object name="文本框" icon="/img/text.ab22920f.png" nodeName="text" fullPath="/html/body/div[1]/div[1]/div[5]/div/div/form/span[1]/input" context="hello world" operation="" as="data" />
</mxCell>
<mxCell id="4" value="点击百度一下" style="nodeStyle;image=/img/button.144b855d.png" parent="1" vertex="1">
<mxGeometry x="220" y="250" width="130" height="35" as="geometry" />
<Object name="按钮" icon="/img/button.144b855d.png" nodeName="button" fullPath="/html/body/div[1]/div[1]/div[5]/div/div/form/span[2]/input" context="" operation="3" as="data" />
</mxCell>
<mxCell id="5" parent="1" source="2" target="3" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="6" parent="1" source="3" target="4" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="7" value="结束" style="nodeStyle;image=/img/over.61db7b65.png" parent="1" vertex="1">
<mxGeometry x="220" y="490" width="130" height="35" as="geometry" />
<Object name="结束" icon="/img/over.61db7b65.png" nodeName="over" fullPath="" context="" operation="" as="data" />
</mxCell>
<mxCell id="8" value="延时器" style="nodeStyle;image=/img/delayed.288d27d6.png" vertex="1" parent="1">
<mxGeometry x="220" y="360" width="130" height="35" as="geometry" />
<Object name="延时器" icon="/img/delayed.288d27d6.png" nodeName="delayed" fullPath="" context="" operation="20000" as="data" />
</mxCell>
<mxCell id="9" edge="1" parent="1" source="4" target="8">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="10" edge="1" parent="1" source="8" target="7">
<mxGeometry relative="1" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
解析xml这里使用的是dom4j. 代码核心类如下图所示:
GraphParse内容如下
package pers.cz.mxgraph;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;
import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
/**
* 解析MxGrapth的图形信息
*/
public class GraphParser {
/**
* XML 文件
*/
private final String xml;
/**
* 图形信息
* @param xml
*/
public GraphParser(String xml) {
this.xml = xml;
}
/**
* 解析MxGrapth
* @return 解析
* @throws ParserConfigurationException 解析配置异常
* @throws SAXException SAX 异常
* @throws IOException Io Exception
*/
public MxGraphModel parse() throws DocumentException {
//1.创建Reader对象
SAXReader reader = new SAXReader();
reader.setEncoding("utf-8");
//2.加载xml
Document document = reader.read(new ByteArrayInputStream(xml.getBytes()));
return new MxGraphModel(document);
}
}
MxCell如下:
package pers.cz.mxgraph;
import org.dom4j.Element;
import java.util.*;
/**
* @program: Reids
* @description: MxCell
* @author: Cheng Zhi
* @create: 2023-01-06 10:18
**/
public class MxCell extends MxElement {
private static final String ATTR_ID = "id";
private static final String ATTR_NAME = "value";
private static final String START_VALUE = "start";
private static final String START_KEY = "nodeName";
private Map<String, Object> params;
private MxGraphModel mxGraphModel;
public MxCell(Element element) {
super(element);
}
public MxCell(Element element, MxGraphModel mxGraphModel) {
super(element);
this.mxGraphModel = mxGraphModel;
}
public Integer getId() {
return Integer.valueOf(getData().get(ATTR_ID));
}
public String getName() {
return getData().get(ATTR_NAME);
}
public MxObject getMxObject() {
return Optional.ofNullable(element.element("Object")).map(object -> new MxObject(object)).orElse(null);
}
public Map<String, String> getMxObjectData() {
return Optional.ofNullable(getMxObject()).map(mxObject -> mxObject.getData()).orElse(new HashMap<>());
}
public Map<String, Object> getParams() {
return params;
}
/**
* 设置自定义参数,用于传递给下个节点
* @param params
*/
public void setParams(Map<String, Object> params) {
this.params = params;
}
/**
* 是否为开始节点
* @return
*/
public Boolean isStart() {
String s = getMxObjectData().get(START_KEY);
if (s != null && START_VALUE.equals(s)) {
return true;
}
return false;
}
/**
* 获取next节点,因为一个节点可能会有多个子节点
* @return
*/
public List<MxCell> getNextCell() {
int currentId = getId();
Integer nextId = 0;
List<MxCell> list = new ArrayList<>();
mxGraphModel.getMxEdges().stream().filter(mxEdge ->mxEdge.getSourceId() == currentId).forEach((p) -> {
list.add(mxGraphModel.getMxCell(p.getTargetId()));
});
return list;
}
/**
* 判断是否还有下个节点
* @return
*/
public boolean hasNext() {
for (MxEdge mxEdge :mxGraphModel.getMxEdges()) {
if (mxEdge.getSourceId() == getId()) {
return true;
}
}
return false;
}
/**
* 获取当前节点的所有上游节点的id
* @return
*/
public List<Integer> getUpstreamNode() {
List<Integer> list = new ArrayList<>();
for (MxEdge mxEdge :mxGraphModel.getMxEdges()) {
if (mxEdge.getTargetId() == getId()) {
list.add(mxEdge.getSourceId());
}
}
return list;
}
/**
* 判断当前节点是否有多个上游节点
* @return
*/
public boolean hasManyUpstreamMode() {
if (getUpstreamNode().size() > 1) {
return true;
}
return false;
}
}
MxEdge内容如下:
package pers.cz.mxgraph;
import org.dom4j.Element;
/**
* @program: Reids
* @description: MxEdge
* @author: Cheng Zhi
* @create: 2023-01-06 11:32
**/
public class MxEdge extends MxElement {
private static final String TRAGET = "target";
private static final String SOURCE = "source";
public MxEdge(Element element) {
super(element);
}
public Integer getTargetId() {
String s = getData().get(TRAGET);
return Integer.valueOf(s);
}
public Integer getSourceId() {
String s = getData().get(SOURCE);
return Integer.valueOf(s);
}
}
MxElement
package pers.cz.mxgraph;
import org.dom4j.Attribute;
import org.dom4j.Element;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @program: Reids
* @description: 抽象xml element
* @author: Cheng Zhi
* @create: 2023-01-06 10:10
**/
public abstract class MxElement {
public Element element;
private Map<String, String> data = new HashMap<String, String>();
public MxElement(Element element) {
this.element = element;
}
public List<Attribute> getAttributes() {
return element.attributes();
}
public Map<String, String> getData() {
List<Attribute> attributes = getAttributes();
for (Attribute attribute : attributes) {
data.put(attribute.getName(), attribute.getValue());
}
return data;
}
}
MxGraphModel
package pers.cz.mxgraph;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @program: Reids
* @description: MxGraphModel
* @author: Cheng Zhi
* @create: 2023-01-06 10:24
**/
public class MxGraphModel {
private List<MxCell> mxCells = new ArrayList<>();
private List<MxObject> mxObjects = new ArrayList<>();
private List<MxEdge> mxEdges = new ArrayList<>();
private Map<Integer, MxCell> mxCellMap = new HashMap<Integer, MxCell>();
private MxCell startCell;
public MxGraphModel(Document document) {
Element rootElement = document.getRootElement();
List<Element> elements = rootElement.elements();
readElement(elements);
}
/**
* 递归解析xml
* @param elements
*/
private void readElement(List<Element> elements) {
for (Element element : elements) {
if (element.getName().equals("mxCell")) {
// 判断是否为边
if (isEdge(element)) {
MxEdge mxEdge = new MxEdge(element);
this.mxEdges.add(mxEdge);
} else {
MxCell mxCell = new MxCell(element, this);
if (mxCell.isStart()) {
this.startCell = mxCell;
}
Integer id = mxCell.getId();
this.mxCellMap.put(id, mxCell);
this.mxCells.add(mxCell);
}
}
if (element.getName().equals("Object")) {
MxObject mxObject = new MxObject(element);
this.mxObjects.add(mxObject);
}
if (element.elements().size() > 0) {
readElement(element.elements());
}
}
}
private Boolean isEdge(Element element) {
Attribute edge = element.attribute("edge");
if (edge == null) {
return false;
}
return true;
}
public List<MxCell> getMxCells() {
return mxCells;
}
public List<MxObject> getMxObjects() {
return mxObjects;
}
public List<MxEdge> getMxEdges() {
return mxEdges;
}
/**
* 获取Map描述的节点集合
* @return
*/
public Map<Integer, MxCell> getMxCellMap() {
return mxCellMap;
}
/**
* 获取节点ID对应的节点
* @param id
* @return
*/
public MxCell getMxCell(Integer id) {
return mxCellMap.get(id);
}
/**
* 获取开始节点
* @return
*/
public MxCell getStartCell() {
if (startCell == null) {
throw new RuntimeException("不合法的流程");
}
return startCell;
}
}
MxObject
package pers.cz.mxgraph;
import org.dom4j.Element;
/**
* @program: Reids
* @description: MxObject
* @author: Cheng Zhi
* @create: 2023-01-06 10:55
**/
public class MxObject extends MxElement {
private static final String ID = "id";
public MxObject(Element element) {
super(element);
}
/*public Integer getId() {
String s = getData().get(ID);
return Integer.valueOf(s);
}*/
}
以上就是一个完整的MxGraph导出xml的java解析方式。
预告
下一篇主要介绍一下MxGraph中的通过图形化的拖拽创建起来的流程后台如何运行起来
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第4天,点击查看活动详情