Pārlūkot izejas kodu

Fix parsing of edge with more than one label

Joeri Exelmans 2 gadi atpakaļ
vecāks
revīzija
e6dce08fe9

+ 4 - 4
drawio2py/abstract_syntax.py

@@ -25,15 +25,15 @@ class Cell(Element):
 
 
 @dataclass(eq=False)
 @dataclass(eq=False)
 class Point(Element):
 class Point(Element):
-	x: Decimal
-	y: Decimal
+	x: Optional[Decimal] # as far as i can tell, these values are not written if they are 0
+	y: Optional[Decimal]
 
 
 @dataclass(eq=False)
 @dataclass(eq=False)
 class VertexGeometry(Element):
 class VertexGeometry(Element):
 	x: Optional[Decimal]
 	x: Optional[Decimal]
 	y: Optional[Decimal]
 	y: Optional[Decimal]
-	width: Decimal
-	height: Decimal
+	width: Optional[Decimal]
+	height: Optional[Decimal]
 	offset: Optional[Point] # Relative offset of the Vertex' label
 	offset: Optional[Point] # Relative offset of the Vertex' label
 
 
 @dataclass(eq=False)
 @dataclass(eq=False)

+ 20 - 11
drawio2py/generator.py

@@ -66,27 +66,36 @@ def generate_diagram(page: Page) -> ET.Element:
 		# Create the actual <mxCell>
 		# Create the actual <mxCell>
 		c = ET.SubElement(par, "mxCell", attrs, **cell.attributes)
 		c = ET.SubElement(par, "mxCell", attrs, **cell.attributes)
 
 
+		def optional_attributes(dict):
+			attrs = {}
+			for key, val in dict.items():
+				if val != None:
+					attrs[key] = str(val)
+			return attrs
+
 		def write_point(parent_xml, point: Point, as_str: Optional[str] = None):
 		def write_point(parent_xml, point: Point, as_str: Optional[str] = None):
-			attrs = {"x": str(point.x), "y": str(point.y)}
-			if as_str != None:
-				attrs['as'] = as_str
+			attrs = optional_attributes({
+				"x": point.x,
+				"y": point.y,
+				"as": as_str,
+			})
 			return ET.SubElement(parent_xml, "mxPoint", attrs)
 			return ET.SubElement(parent_xml, "mxPoint", attrs)
 
 
 		# Geometry
 		# Geometry
 		if isinstance(cell, Vertex):
 		if isinstance(cell, Vertex):
-			g = ET.SubElement(c, "mxGeometry", {
-				"x": str(cell.geometry.x),
-				"y": str(cell.geometry.y),
-				"width": str(cell.geometry.width),
-				"height": str(cell.geometry.height),
-				"as": "geometry"
-			})
+			g = ET.SubElement(c, "mxGeometry", optional_attributes({
+				"x": cell.geometry.x,
+				"y": cell.geometry.y,
+				"width": cell.geometry.width,
+				"height": cell.geometry.height,
+				"as": "geometry",
+			}))
 			if cell.geometry.offset != None:
 			if cell.geometry.offset != None:
 				write_point(g, cell.geometry.offset, "offset")
 				write_point(g, cell.geometry.offset, "offset")
 		elif isinstance(cell, Edge):
 		elif isinstance(cell, Edge):
 			g = ET.SubElement(c, "mxGeometry", {
 			g = ET.SubElement(c, "mxGeometry", {
 				"relative": "1",
 				"relative": "1",
-				"as": "geometry"
+				"as": "geometry",
 			})
 			})
 			if len(cell.geometry.points) > 0:
 			if len(cell.geometry.points) > 0:
 				a = ET.SubElement(g, "Array", {"as": "points"})
 				a = ET.SubElement(g, "Array", {"as": "points"})

+ 2 - 2
drawio2py/parser.py

@@ -64,8 +64,8 @@ class Parser:
 		if groot is None: return None
 		if groot is None: return None
 		offset_xml = groot.find(".//mxPoint[@as='offset']")
 		offset_xml = groot.find(".//mxPoint[@as='offset']")
 		offset = None if offset_xml == None else Parser.parse_point(offset_xml)
 		offset = None if offset_xml == None else Parser.parse_point(offset_xml)
-		return VertexGeometry(groot.get("x", None), groot.attrib.get("y", None),
-		                    groot.attrib["width"], groot.attrib["height"],
+		return VertexGeometry(groot.get("x", None), groot.get("y", None),
+		                    groot.get("width", None), groot.get("height", None),
 		                    offset=offset)
 		                    offset=offset)
 
 
 	@staticmethod
 	@staticmethod

+ 27 - 0
test/data/edgeLabel.drawio

@@ -0,0 +1,27 @@
+<mxfile host="Electron" modified="2023-06-20T15:17:44.069Z" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/21.2.8 Chrome/114.0.5735.45 Electron/25.0.1 Safari/537.36" etag="uWCH2RuiU4VNz75uNGWD" version="21.2.8" type="device">
+  <diagram name="Page-1" id="c7YBU_xrP0pCo13Y-Qku">
+    <mxGraphModel dx="1531" dy="1700" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
+      <root>
+        <mxCell id="0" />
+        <mxCell id="1" parent="0" />
+        <mxCell id="zC1wFdxtIY5PVFzHPPmW-1" value="label" style="endArrow=classic;html=1;rounded=0;" edge="1" parent="1">
+          <mxGeometry x="-0.3081" y="-129" width="50" height="50" relative="1" as="geometry">
+            <mxPoint as="sourcePoint" />
+            <mxPoint x="220" y="160" as="targetPoint" />
+            <mxPoint as="offset" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="zC1wFdxtIY5PVFzHPPmW-2" value="hey" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="zC1wFdxtIY5PVFzHPPmW-1">
+          <mxGeometry x="0.4091" y="-1" relative="1" as="geometry">
+            <mxPoint x="5" y="-34" as="offset" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="zC1wFdxtIY5PVFzHPPmW-7" value="test" style="rounded=0;whiteSpace=wrap;html=1;noLabel=0;treeFolding=0;treeMoving=0;enumerate=0;comic=0;movableLabel=1;" vertex="1" parent="1">
+          <mxGeometry x="280" width="120" height="60" as="geometry">
+            <mxPoint x="32" y="-10" as="offset" />
+          </mxGeometry>
+        </mxCell>
+      </root>
+    </mxGraphModel>
+  </diagram>
+</mxfile>

+ 3 - 0
test/run_tests.py

@@ -55,6 +55,9 @@ class Tests(unittest.TestCase):
         # with open(os.path.join(DATADIR, "labelOffset-1.drawio"), 'wb') as f:
         # with open(os.path.join(DATADIR, "labelOffset-1.drawio"), 'wb') as f:
         #     generator.generate(asyntax, f)
         #     generator.generate(asyntax, f)
 
 
+    def test_edge_label(self):
+        run_test("edgeLabel.drawio")
+
     def test_shapelib(self):
     def test_shapelib(self):
         common_lib = parse_shapelib("shapelibs/common.xml")
         common_lib = parse_shapelib("shapelibs/common.xml")
         pm_lib = parse_shapelib("shapelibs/pm.xml")
         pm_lib = parse_shapelib("shapelibs/pm.xml")