Wrapping with Nokogiri - ruby
I apologize if this has been answered, but I can't find the correct way to get this working. I'm using Nokogiri to modify SVG diagrams that are generated through an application and I hit a bit of a snag. The code I'm working with looks something like this:
<svg>
<g id="1">
<text>lorem</text>
<text>ipsum</text>
</g>
<g id="2">
<text>lorem</text>
<text>ipsum</text>
</g>
<g id="3">
<text>lorem</text>
<text>ipsum</text>
</g>
<svg>
I'd like to have this appended to every document as it is analyzed by the script:
<svg>
<g id="scale" transform="scale(1.0)">
<g id="1">
<text>lorem</text>
<text>ipsum</text>
</g>
<g id="2">
<text>lorem</text>
<text>ipsum</text>
</g>
<g id="3">
<text>lorem</text>
<text>ipsum</text>
</g>
</g>
<svg>
I've tried using methods such as before and after but it won't work correctly in this situation. Ideally I'd just wrap the entirety of the nodeset with wrap, but I can't figure out how to get it to work across all sets rather than on every nodeset. Any guidance would be much appreciated.
Thanks!
Here's how I'd do it:
require 'nokogiri'
doc = Nokogiri::XML(<<EOT)
<svg>
<g id="1">
<text>lorem</text>
<text>ipsum</text>
</g>
<g id="2">
<text>lorem</text>
<text>ipsum</text>
</g>
<g id="3">
<text>lorem</text>
<text>ipsum</text>
</g>
</svg>
EOT
svg = doc.at('svg')
svg.children = '<g id="scale" transform="scale(1.0)">' + svg.children.to_xml + '</g>'
puts svg.to_xml
Running that outputs:
<svg>
<g id="scale" transform="scale(1.0)">
<g id="1">
<text>lorem</text>
<text>ipsum</text>
</g>
<g id="2">
<text>lorem</text>
<text>ipsum</text>
</g>
<g id="3">
<text>lorem</text>
<text>ipsum</text>
</g>
</g>
</svg>
Nokogiri nicely lets us define nodes as strings, and coerces them to XML::Node objects. Give it a string containing XML and it'll convert it into a NodeSet, so we can cleanly and clearly manipulate the XML DOM without having to write u-gly code.
doc = Nokogiri.XML( raw_svg )
wrapper_g = doc.create_element('g', 'id' => "scale", 'transform' => "scale(1.0)")
doc.xpath('/svg/g').each {|elem| wrapper_g << elem }
doc.root << wrapper_g
Optional - remove empty text nodes:
doc.xpath('//text()').each {|t| t.text =~ /\A\s*\z/ and t.remove }
The cheat sheet might help.
require 'nokogiri'
doc = Nokogiri::XML(%Q{
<svg>
<g id="1">
<text>lorem</text>
<text>ipsum</text>
</g>
<g id="2">
<text>lorem</text>
<text>ipsum</text>
</g>
<g id="3">
<text>lorem</text>
<text>ipsum</text>
</g>
</svg>
})
svg = doc.xpath('//svg')[0]
wrapper = doc.create_element('g', 'id' => 'scale', 'transform' => 'scale(1.0)')
wrapper.children = svg.children
svg.add_child wrapper
puts doc
Note that you missed the slash at the closing svg tag.
Related
SVG image does not show up in browsers
I have this SVG image, made in Inkscape which shows the following in Inkscape: However, when I open the SVG in a browser (Chrome, Firefox), nothing appears. I have tried adding "simple" lines and objects to the image, and they DO appear, so it seems to be something with this specific object. What could it be? And how to fix it? <?xml version="1.0" encoding="UTF-8" standalone="no"?> <!-- Created with Inkscape (http://www.inkscape.org/) --> <svg width="65.834572mm" height="70.733879mm" viewBox="0 0 65.834572 70.733879" version="1.1" id="svg13961" inkscape:version="1.2.1 (9c6d41e410, 2022-07-14, custom)" sodipodi:docname="test.svg" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"> <sodipodi:namedview id="namedview13963" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:showpageshadow="2" inkscape:pageopacity="0.0" inkscape:pagecheckerboard="0" inkscape:deskcolor="#d1d1d1" inkscape:document-units="mm" showgrid="false" inkscape:zoom="0.63874158" inkscape:cx="161.25457" inkscape:cy="270.06227" inkscape:window-width="529" inkscape:window-height="862" inkscape:window-x="534" inkscape:window-y="18" inkscape:window-maximized="1" inkscape:current-layer="layer1" /> <defs id="defs13958"> <clipPath clipPathUnits="userSpaceOnUse" id="clipPath16097"> <g id="g16109"> <g id="g16107" transform="translate(162.0894,-8.96869)"> <g id="g16105"> <g id="g16103"> <g id="g16101"> <path d="M 0,595.2 H 841.7 V 0 H 0 Z" id="path16099" /> </g> </g> </g> </g> </g> </clipPath> </defs> <g inkscape:label="Layer 1" inkscape:groupmode="layer" id="layer1" transform="translate(-61.940456,-78.545196)"> <path d="m 384.899,184.03111 c 40.89063,-0.26977 82.65532,5.96811 119.21947,25.15083 23.45592,12.13347 47.3093,25.37475 74.13169,27.82215 6.70195,0.79044 13.4529,1.13004 20.19984,1.13002" style="display:inline;opacity:1;fill:none;stroke:#000000;stroke-width:127.501;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path60" clip-path="url(#clipPath16097)" transform="matrix(0.00761114,0.32814968,0.35268292,-0.00818017,16.590019,-45.732392)" /> </g> </svg>
How to make sense of id and title?
I would like to identify my nodes via Javascript and hence ensure that each element (graph, node, edge) has a unique ID. I found the https://github.com/magjac/d3-graphviz#maintaining-object-constancy section and thought that.keyMode('id') would tell d3-graphviz to use my IDs. But ids are still using the graph ID and don't seem to use the node ID. I found instead a title attribute from this example: https://bl.ocks.org/magjac/28a70231e2c9dddb84b3b20f450a215f What is this attribute? Can I be sure that it is the ID I am looking for? What is the relationship in D3-graphviz between id and title? EDIT I tried to dig and came up with this simple Example. I have this (autogenerated) input file: digraph { label="" id="g1" n1 [id="n1", label="First Node"] n2 [id="n2", label="Second Node"] n1 -> n2 [id="e1", arrowHead="normal", arrowTail="dot"] } I get this outcome: <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="134pt" height="116pt" viewBox="0.00 0.00 133.59 116.00"> <g id="g1" class="graph" transform="translate(4,112) scale(1)"> <polygon fill="white" stroke="transparent" points="-4,4 -4,-112 129.59,-112 129.59,4 -4,4"></polygon> <!-- n1 --> <g id="n1" class="node"> <title>n1</title> <ellipse fill="none" stroke="black" cx="62.8" cy="-90" rx="52.16" ry="18"></ellipse> <text text-anchor="middle" x="62.8" y="-85.8" font-family="Times,serif" font-size="14.00">First Node</text> </g> <!-- n2 --> <g id="n2" class="node"> <title>n2</title> <ellipse fill="none" stroke="black" cx="62.8" cy="-18" rx="62.59" ry="18"></ellipse> <text text-anchor="middle" x="62.8" y="-13.8" font-family="Times,serif" font-size="14.00">Second Node</text> </g> <!-- n1->n2 --> <g id="e1" class="edge"> <title>n1->n2</title> <path fill="none" stroke="black" d="M62.8,-71.7C62.8,-63.98 62.8,-54.71 62.8,-46.11"></path> <polygon fill="black" stroke="black" points="66.3,-46.1 62.8,-36.1 59.3,-46.1 66.3,-46.1"></polygon> </g> </g> </svg> but when I programmatically in an mouse event that provides me the <g> for a node, then I get the ID: svg-0.g1.n2 The last bit created the confusion. I need to find the attribute value, and not a connected value. But that will work. Thanks!
The underlying Graphviz language provides an id attribute (https://www.graphviz.org/docs/attrs/id/). Based on the d3-graphviz consistency text, it looks like d3-graphviz will honor this id attribute.
d3.js label inside path deformed
i added a label inside a path successfully but when i try to center this label by changing manually x and dy attributes. the label deforms in the center. here is some picture and its corresponding code. before changing the x attributes its value 135: <svg width="1306" height="628"> <g> <path name="cf40" d="M590.3383838385344,295.20151514932513L756.3916666656733,317.13308080658317L878.5818181820214,279.5361111164093L822.186363636516,527.0494949556887L728.1939393933862,555.2472222223878Z" id="polygon2" style="fill: steelblue;"></path> </g> <text x="135" dy="105"><textPath xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#polygon2">CF40</textPath></text> </svg> after changing the x attributes new value is 145: <svg width="1306" height="628"> <g> <path name="cf40" d="M590.3383838385344,295.20151514932513L756.3916666656733,317.13308080658317L878.5818181820214,279.5361111164093L822.186363636516,527.0494949556887L728.1939393933862,555.2472222223878Z" id="polygon2" style="fill: steelblue;"></path> </g> <text x="145" dy="105"><textPath xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#polygon2">CF40</textPath></text> </svg>
There is nothing "deformed" here. That's the expected behaviour: you're using a textPath to position the text, and the path you're referencing changes orientation at the first L command. You can clearly see that there is nothing wrong when we draw some (red) lines, showing this "bend": <svg width="400" height="300"> <g> <path name="cf40" d="M590.3383838385344,295.20151514932513L756.3916666656733,317.13308080658317L878.5818181820214,279.5361111164093L822.186363636516,527.0494949556887L728.1939393933862,555.2472222223878Z" id="polygon2" style="fill: steelblue;" transform="translate(-500,-260)"></path> </g> <text x="145" dy="105"><textPath xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#polygon2">CF40</textPath></text> <line x1="756.3916666656733" y1="317.133080" x2="728.1939393933862" y2="555.2472222223878" stroke="red" transform="translate(-500,-260)" ></line> <line x1="756.3916666656733" y1="317.133080" x2="822.186363636516" y2="527.049" stroke="red" transform="translate(-500,-260)" ></line> </svg> And you can see that even better if we create several texts, increasing the dy up to your value (105): <svg width="400" height="300"> <g> <path name="cf40" d="M590.3383838385344,295.20151514932513L756.3916666656733,317.13308080658317L878.5818181820214,279.5361111164093L822.186363636516,527.0494949556887L728.1939393933862,555.2472222223878Z" id="polygon2" style="fill: steelblue;" transform="translate(-500,-260)"></path> </g> <text x="145" dy="15"><textPath xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#polygon2">CF40</textPath></text> <text x="145" dy="40"><textPath xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#polygon2">CF40</textPath></text> <text x="145" dy="60"><textPath xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#polygon2">CF40</textPath></text> <text x="145" dy="80"><textPath xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#polygon2">CF40</textPath></text> <text x="145" dy="105"><textPath xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#polygon2">CF40</textPath></text> <line x1="756.3916666656733" y1="317.133080" x2="728.1939393933862" y2="555.2472222223878" stroke="red" transform="translate(-500,-260)" ></line> <line x1="756.3916666656733" y1="317.133080" x2="822.186363636516" y2="527.049" stroke="red" transform="translate(-500,-260)" ></line> </svg> Possible solution: alternatively, you can draw a curve. That way, the text will follow the path without breaks: <svg width="400" height="300"> <g> <path name="cf40" d="M590.3383838385344,295.20151514932513 C 756 327,756 327, 878.5818181820214,279.5361111164093L822.186363636516,527.0494949556887L728.1939393933862,555.2472222223878Z" id="polygon2" style="fill: steelblue;" transform="translate(-500,-260)"></path> </g> <text x="145" dy="105"><textPath xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#polygon2">CF40</textPath></text> </svg>
SVG animation scaling while keeping the group from moving on one end
I am trying to use svg animation to get a dragonfly to flap its wings. I am doing this by scaling the left and right wing on the x axis. the problem is when I scale it the wing moves. I want the left or right edge of the wing to stay in one spot when it scales. here is the code for one wing <g id="wing_left"> <g> <path fill="#88C9CE" d="M254.8,132.1c-66.2,6.7-130.7,21.1-193.3,47.2c-7.4,3.1-58.6,24.1-44.8,37.4 c15.2,14.8,88.3,17.3,109.3,11.3C162.6,217.8,279.4,129.7,254.8,132.1z"/> <path fill="#92D9DE" d="M237.3,113.7c-16.1,3.6-245.9-31.8-250-22.3c-11.5,26.7,38.3,51.9,56.1,58.2 c88.5,31.4,185.6,6.2,202.5-11.3C251.7,132.4,247.9,111.3,237.3,113.7z"/> <path fill="#FFFFFF" d="M-1.2,97.7c9.1-4.5,84.8,7.2,83.7,7.1c-16.4-1.7-49.9-3.3-56.9-3.5c-32.2-1.2-24,7.4-22.5,11.8 C5,118.4-7.2,100.6-1.2,97.7z"/> <path fill="#76B0B3" d="M249.3,145.5c-2.9,3-8,7.3-11.5,10.2c-21.1,17.5-102.1,8.9-102.1,8.9s54.5-2.2,86-13.4 c13.2-4.7,21-10.2,23.2-12c0,0,1.1,1.4,2.1,2.5c1,1.1,2.3,1.8,2.3,1.8S249.3,145.5,249.3,145.5z"/> </g> <animateTransform id="wlFlapDown" attributeName="transform" type="scale" from="1 1" to="0.5 1" begin="0s;wlFlapUp.end" dur="160ms" repeatCount="indefinite" fill="freeze" /> <animateTransform id="wlFlapUp" attributeName="transform" type="scale" from="0.5 1" to="1 1" begin="wlFlapDown.end" dur="160ms" repeatCount="indefinite" fill="freeze" /> </g> Here is the whole svg code or you can see it in codepen <?xml version="1.0" encoding="utf-8"?> <!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="-14.4 7.7 550.5 426.8" enable-background="new -14.4 7.7 550.5 426.8" xml:space="preserve"> <g id="wing_left"> <g> <path fill="#88C9CE" d="M254.8,132.1c-66.2,6.7-130.7,21.1-193.3,47.2c-7.4,3.1-58.6,24.1-44.8,37.4 c15.2,14.8,88.3,17.3,109.3,11.3C162.6,217.8,279.4,129.7,254.8,132.1z"/> <path fill="#92D9DE" d="M237.3,113.7c-16.1,3.6-245.9-31.8-250-22.3c-11.5,26.7,38.3,51.9,56.1,58.2 c88.5,31.4,185.6,6.2,202.5-11.3C251.7,132.4,247.9,111.3,237.3,113.7z"/> <path fill="#FFFFFF" d="M-1.2,97.7c9.1-4.5,84.8,7.2,83.7,7.1c-16.4-1.7-49.9-3.3-56.9-3.5c-32.2-1.2-24,7.4-22.5,11.8 C5,118.4-7.2,100.6-1.2,97.7z"/> <path fill="#76B0B3" d="M249.3,145.5c-2.9,3-8,7.3-11.5,10.2c-21.1,17.5-102.1,8.9-102.1,8.9s54.5-2.2,86-13.4 c13.2-4.7,21-10.2,23.2-12c0,0,1.1,1.4,2.1,2.5c1,1.1,2.3,1.8,2.3,1.8S249.3,145.5,249.3,145.5z"/> </g> <animateTransform id="wlFlapDown" attributeName="transform" type="scale" from="1 1" to="0.5 1" begin="0s;wlFlapUp.end" dur="160ms" repeatCount="indefinite" fill="freeze" /> <animateTransform id="wlFlapUp" attributeName="transform" type="scale" from="0.5 1" to="1 1" begin="wlFlapDown.end" dur="160ms" repeatCount="indefinite" fill="freeze" /> </g> <g id="wing_right"> <g> <path fill="#88C9CE" d="M275.9,134c66.4,4.7,131.2,17.1,194.6,41.4c7.5,2.9,59.3,22.3,45.9,36.1c-14.8,15.2-87.7,19.9-109,14.6 C370.6,216.9,251.2,132.2,275.9,134z"/> <path fill="#92D9DE" d="M285,113c16.2,3.1,244.8-39.1,249.2-29.7c12.3,26.3-36.8,53-54.4,59.8c-87.6,34-185.4,11.7-202.8-5.2 C271.1,132.1,274.2,110.9,285,113z"/> <path fill="#FFFFFF" d="M451.2,98.5c25.6-4.3,28.9-4.8,58.9-8.8c1.9-0.3,16.3-1.3,15.6,4.3c-0.2,1.4-6.5,17.8-6,13.2 c0.1-0.8,0.9-9.8-1.3-12.5C513.9,88.7,445.7,99.5,451.2,98.5z"/> <path fill="#76B0B3" d="M291.3,155.4c21.9,16.6,99.9,5.4,99.9,5.4s-54.7-0.2-86.7-9.9c-13.4-4.1-22.5-9.1-24.1-10.3 c0,0-0.8,0.9-1.8,1.6c0,0,0.1,2.2,0.1,2.2S287.6,152.7,291.3,155.4z"/> </g> <animateTransform id="wrFlapDown" attributeName="transform" type="scale" from="1 1" to="0.5 1" begin="0s; wrFlapUp.end" dur="160ms" repeatCount="indefinite" fill="freeze" /> <animateTransform id="wrFlapDown" attributeName="transform" type="scale" from="0.5 1" to="1 1" begin="wrFlapDown.end" dur="160ms" repeatCount="indefinite" fill="freeze" /> </g> <g id="body" xmlns:inkpad="http://taptrix.com/inkpad/svg_extensions"> <g id="Layer_2" inkpad:layerName="body"> <path fill="#D9AC32" d="M253.8,83.2c-4.5-29.5-6.4-53.2-16-74.7c-0.8-1.9-4.3,1-3.4,1.6c0.4,0.2,12.6,13.5,17.3,73.2 C252.2,88.9,254.5,87.3,253.8,83.2z"/> <path fill="#D9AC32" d="M272.2,82.6c5.2-29.3,7.8-53,17.9-74.3c0.9-1.9,4.3,1.1,3.3,1.7c-0.4,0.2-12.9,13.2-19.1,72.7 C273.7,88.2,271.5,86.6,272.2,82.6z"/> <path fill="#FFE008" d="M249.8,128.8l28.2-0.4c0,0,10.4,208,2.7,260.4c-10.3,71.1-18.9,49.7-27.9,0.4 C243.4,337.1,249.8,128.8,249.8,128.8z"/> <path fill="#FFE008" d="M242.5,130.2c-0.2-12,9-21.8,20.6-22c11.5-0.2,21.1,9.4,21.2,21.4c0.2,12-9.7,17-21.2,17.2 C251.5,146.9,242.7,142.2,242.5,130.2z"/> <path fill="#FFE008" d="M236.8,110.7c-0.3-18.4,12-32.8,26.5-33c14.5-0.2,25.8,13.9,26.1,32.2c0.3,18.4-11.7,25.1-26.3,25.3 C248.6,135.4,237.1,129,236.8,110.7z"/> </g> <g id="Layer_3" inkpad:layerName="eyes"> <g> <path fill="#F5F2E1" d="M227.8,95.9c-0.1-8.3,7.2-15.1,16.4-15.3c9.2-0.1,16.7,6.5,16.8,14.8c0.1,8.3-7.2,15.1-16.4,15.3 C235.4,110.9,227.9,104.2,227.8,95.9z"/> <path d="M255.1,92c-0.6,1.6-7.3-5.5-19.7,3.7c-2.4,1.8-1.8-4.6-0.1-6C244.1,82.6,255.8,90.4,255.1,92z"/> <path fill="#D8E6C3" d="M228,96.2c-0.1-5.4,2.1,9.9,15.5,11.1c8.1,0.7,14.5-2.9,14.2-2.5c-3.9,4.4-9,5.5-10.5,5.7 C236.8,111.8,228.2,106.5,228,96.2z"/> </g> <g> <path fill="#F5F2E1" d="M295.8,94.9c-0.1-8.3-7.7-14.9-16.8-14.8c-9.2,0.1-16.5,7-16.4,15.3c0.1,8.3,7.7,14.9,16.8,14.8 C288.6,110.1,295.9,103.2,295.8,94.9z"/> <path d="M268.3,91.8c0.7,1.6,7.1-5.7,19.8,3.1c2.5,1.7,1.7-4.7-0.1-6C279.1,82.1,267.6,90.3,268.3,91.8z"/> <path fill="#D8E6C3" d="M295.5,95.2c-0.1-5.4-1.8,9.9-15.2,11.5c-8.1,1-14.6-2.5-14.3-2.1c4,4.3,9.2,5.2,10.7,5.4 C287.2,111,295.7,105.5,295.5,95.2z"/> </g> </g> <path fill="#E5C907" d="M242.6,127.9c0-0.1,4.8,8.1,22.5,7.2c13.6-0.7,19-8.1,19-8.1c-0.4,4.9-11.3,11.2-18.3,11.6 C260.3,139,247.3,137.3,242.6,127.9z"/> <path fill="#E5C907" d="M249.3,143.6c0,0,6,3.9,15,3.2c10.4-0.8,14.4-4.7,14.4-4.6c0.2,4.1,0.5,8.3,0.4,8.6 c-3.5,7.1-20.6,9.4-29.8,2C249,152.5,249.3,147.1,249.3,143.6z"/> </g> </svg>
The problem here is that the origin for all scale transforms is at (0,0) which is at the top left of the SVG. So your scale animations are centred on the left side of the SVG (x=0). Basically you need to move the coordinate space for the wings, so that when the scale is applied, the wings are centred on x=0. So the steps would be: Use a translate transform to move your wings so they are centred at x=0 apply your scale animation in this coordinate space surround that with a group with a transform that moves them back to their original position For example: <g id="wings" transform="translate(270,0)"> <g> <g transform="translate(-270,0)"> <g "left wing"> <g "right wing"> </g> <animateTransform .../> </g> </g> Demo here
Remove rectangle from Graphviz Dot cluster subgraph
Is there a way to tell Dot to use a cluster but not show the rectangle around the subgraph nodes?
You can do this with style. Example using style=invis: digraph g{ subgraph cluster0 { style=invis; 1 -> 2; } } If you'd like to use this as a default for all subgraphs, use subgraph[style=invis] : digraph g{ subgraph[style=invis]; subgraph cluster0 { 1 -> 2; } } Edit: 9 years later... The best solution is to use peripheries=0 This will actually prevent generating the rectangle in svg output, whereas penwidth=0 still includes a polygon (with stroke-width="0", but it's still there). I've added this since this is the most upvoted answer.
You can use style=invis: subgraph cluster1 { style=invis ... } As an alternative to the style=invis approach above, you can also set pencolor=transparent (either locally or globally).
This can be done by using the penwidth = 0 attribute. This neither affects the label text nor changes the bounding box of the cluster. Depending on the graphics driver this may output a zero width boundary. Using the suggested peripheries = 0 attribute forces the default rectangular surround to be removed as a side effect. Although the style = invis and pencolor = transparent attributes work in most cases, there may be a need to avoid squashing the cluster label and leaving a transparent line around the cluster. As noted by #marapet, peripheries=0 will remove the hairline from vector output formats like SVG that could be processed further.
You can also use peripheries=0
Use penwidth = 0 within subgraphs for which you don't want border. This is how I am using it. It only removes the cluster border and does not cause any side effect as in with style = invis which also tends to removes the graph labels (undesired in my case). digraph { subgraph cluster2 { label="set" subgraph cluster0 { penwidth = 0 label="hello" 1 -> 2; } subgraph cluster1 { //penwidth = 0 label="world" 3 -> 2; } } } check out the live preview here <?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <!-- Generated by graphviz version 2.40.1 (20161225.0304) --> <!-- Title: %0 Pages: 1 --> <svg width="188pt" height="214pt" viewBox="0.00 0.00 188.00 213.60" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 209.6)"> <title>%0</title> <polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-209.6 184,-209.6 184,4 -4,4"/> <g id="clust1" class="cluster"> <title>cluster2</title> <polygon fill="none" stroke="#000000" points="8,-8 8,-197.6 172,-197.6 172,-8 8,-8"/> <text text-anchor="middle" x="90" y="-181" font-family="Times,serif" font-size="14.00" fill="#000000">set</text> </g> <g id="clust2" class="cluster"> <title>cluster0</title> <polygon fill="none" stroke="#000000" stroke-width="0" points="94,-16 94,-164.8 164,-164.8 164,-16 94,-16"/> <text text-anchor="middle" x="129" y="-148.2" font-family="Times,serif" font-size="14.00" fill="#000000">hello</text> </g> <g id="clust3" class="cluster"> <title>cluster1</title> <polygon fill="none" stroke="#000000" points="16,-88 16,-164.8 86,-164.8 86,-88 16,-88"/> <text text-anchor="middle" x="51" y="-148.2" font-family="Times,serif" font-size="14.00" fill="#000000">world</text> </g> <!-- 1 --> <g id="node1" class="node"> <title>1</title> <ellipse fill="none" stroke="#000000" cx="129" cy="-114" rx="27" ry="18"/> <text text-anchor="middle" x="129" y="-109.8" font-family="Times,serif" font-size="14.00" fill="#000000">1</text> </g> <!-- 2 --> <g id="node2" class="node"> <title>2</title> <ellipse fill="none" stroke="#000000" cx="129" cy="-42" rx="27" ry="18"/> <text text-anchor="middle" x="129" y="-37.8" font-family="Times,serif" font-size="14.00" fill="#000000">2</text> </g> <!-- 1->2 --> <g id="edge1" class="edge"> <title>1->2</title> <path fill="none" stroke="#000000" d="M129,-95.8314C129,-88.131 129,-78.9743 129,-70.4166"/> <polygon fill="#000000" stroke="#000000" points="132.5001,-70.4132 129,-60.4133 125.5001,-70.4133 132.5001,-70.4132"/> </g> <!-- 3 --> <g id="node3" class="node"> <title>3</title> <ellipse fill="none" stroke="#000000" cx="51" cy="-114" rx="27" ry="18"/> <text text-anchor="middle" x="51" y="-109.8" font-family="Times,serif" font-size="14.00" fill="#000000">3</text> </g> <!-- 3->2 --> <g id="edge2" class="edge"> <title>3->2</title> <path fill="none" stroke="#000000" d="M67.1617,-99.0816C78.3214,-88.7802 93.3334,-74.923 105.7715,-63.4417"/> <polygon fill="#000000" stroke="#000000" points="108.1519,-66.0076 113.1259,-56.653 103.4039,-60.864 108.1519,-66.0076"/> </g> </g> </svg>