I am trying to convert XML to SVG using Java, but it looks like the shapes information is getting lost in the process.
Given a simple draw.io
graph:
After running XmlToSvg.java I get:
I saved it as an uncompressed XML. I'm using the mxgraph-all.jar
from the mxGraph Repo
Do you know if there are hidden settings to enable to preserve shapes and colors?
Short version
It looks like despite the claims on the GitHub page, no implementation except for JavaScript one is really fully featured and production ready. Particularly Java implementation (as well .Net and PHP server-side ones) doesn't support "Cube" shape out of the box.
More details
Colors
You didn't provide your example XML but when I generate similar graph I get something like
<?xml version="1.0" encoding="UTF-8"?>
<mxGraphModel dx="1426" dy="816" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850"
pageHeight="1100" background="#ffffff" math="0" shadow="0">
<root>
<mxCell id="0"/>
<mxCell id="1" parent="0"/>
<mxCell id="2" value="" style="ellipse;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="445" y="60" width="230" height="150" as="geometry"/>
</mxCell>
<mxCell id="3" value="" style="ellipse;shape=doubleEllipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1">
<mxGeometry x="500" y="320" width="120" height="120" as="geometry"/>
</mxCell>
<mxCell id="4" value="" style="endArrow=classic;html=1;" parent="1" source="3" target="2" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="430" y="510" as="sourcePoint"/>
<mxPoint x="480" y="460" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="5" value="" style="shape=cube;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="80" y="320" width="170" height="110" as="geometry"/>
</mxCell>
</root>
</mxGraphModel>
Important thing here is that this XML does not contain any information about colors. Thus whole idea about "preserving colors" is wrong. In Java implementation you can configure "default colors" using an instance of mxStylesheet
class and use it to init mxGraph
object. For example to change colors to black and white you may do something like this:
mxStylesheet stylesheet = new mxStylesheet();
// configure "figures" aka "vertex"
{
Map<String, Object> style = stylesheet.getDefaultVertexStyle();
style.put(mxConstants.STYLE_FILLCOLOR, "#FFFFFF");
style.put(mxConstants.STYLE_STROKECOLOR, "#000000");
style.put(mxConstants.STYLE_FONTCOLOR, "#000000");
}
// configure "lines" aka "edges"
{
Map<String, Object> style = stylesheet.getDefaultEdgeStyle();
style.put(mxConstants.STYLE_STROKECOLOR, "#000000");
style.put(mxConstants.STYLE_FONTCOLOR, "#000000");
}
mxGraph graph = new mxGraph(stylesheet);
You may look at mxStylesheet.createDefaultVertexStyle and mxStylesheet.createDefaultEdgeStyle for some details.
Shapes
The "ellipse" shape is not handled correctly because there is no code to parse "ellipse;whiteSpace=wrap;html=1;"
and understand that the shape should be "ellipse" (comapre this to the "double ellipse" style "ellipse;shape=doubleEllipse;whiteSpace=wrap;html=1;aspect=fixed;"
that contains explicit shape
value). In JS implementation the first part of the style seems to select a handler function that will handle the rest of the string and do actual work. There seems to be no such feature in Java implmenetation at all. You can work this around by using "named styles" feature and define default shape for corresponding "handler" in the same mxStylesheet
object like this:
// I just copied the whole list of mxConstants.SHAPE_ here
// you probably should filter it by removing non-primitive shapes
// such as mxConstants.SHAPE_DOUBLE_ELLIPSE
String[] shapes = new String[] {
mxConstants.SHAPE_RECTANGLE,
mxConstants.SHAPE_ELLIPSE,
mxConstants.SHAPE_DOUBLE_RECTANGLE,
mxConstants.SHAPE_DOUBLE_ELLIPSE,
mxConstants.SHAPE_RHOMBUS,
mxConstants.SHAPE_LINE,
mxConstants.SHAPE_IMAGE,
mxConstants.SHAPE_ARROW,
mxConstants.SHAPE_CURVE,
mxConstants.SHAPE_LABEL,
mxConstants.SHAPE_CYLINDER,
mxConstants.SHAPE_SWIMLANE,
mxConstants.SHAPE_CONNECTOR,
mxConstants.SHAPE_ACTOR,
mxConstants.SHAPE_CLOUD,
mxConstants.SHAPE_TRIANGLE,
mxConstants.SHAPE_HEXAGON,
};
Map<String, Map<String, Object>> styles = stylesheet.getStyles();
for (String sh : shapes)
{
Map<String, Object> style = new HashMap<>();
style.put(mxConstants.STYLE_SHAPE, sh);
styles.put(sh, style);
}
Still you may notice that the list of the mxConstants.SHAPE_
doesn't contain "cube". In JS implementation "cube" is a compound shape that is handled by a specialized handler in examples/grapheditor/www/js/Shape.js which is not a part of the core library! It means that if you want to support such advanced shapes in your Java code, you'll have to roll out the code to handle it yourself.
P.S. With all those changes (hacks) the image I get using Java code from the XML in the first snippet is:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With