0

I have the below XSLT (thanks to Martin Honnen), and following there is the svg to transform. I would like to center the created blocks containing text to the random shapes below (they could have any number of points). So I would need to enter the x and y coordinates in this blocks <text x="" y="" id="{$id}-text"> and <tspan id="{$id}-tspan" x="" y="">, however they would have to be dinamically calculated since each of the shape could be anywhere in each drawing. I understand that I would have to create a file containing javascript and the second solution would fit as the whole process would be called from a VBA macro, that uses the method GetBBox(), however I do not understand how to use is in the XSLT (nor could I actually grab such js code as there seem to be different versions of it, or I am just too ignorant about js to notice it, ). In the end, I think it should be rather trivial: in the x ther would be the subtraction of x the parent group and its width, divided by 2, and similarly for the height. But I just do not know how to fix it with the @id and the rest.

XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:svg="http://www.w3.org/2000/svg"
    xmlns="http://www.w3.org/2000/svg"
    exclude-result-prefixes="svg"
    version="1.0">
  
  <xsl:strip-space elements="*"/>
  
  <xsl:template match="svg:g[@id[starts-with(., 'Item')]]">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
      <xsl:variable name="id" select="substring-before(@id, '-')"/>
      <text x="" y="" id="{$id}-text">
        <tspan id="{$id}-tspan" x="" y="">
          <xsl:value-of select="$id"/>
        </tspan>
      </text>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

SVG

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="exportSvg" width="400" height="400">
    <defs/>
    <rect width="400" height="400" transform="translate(0, 0)" fill="rgb(255, 255, 255)" style="fill:rgb(255, 255, 255);"/>
    <g>
        <g id="Drawing-svg" clip-path="url(#rect-mask-Drawing)">
            <clipPath id="rect-mask-Drawing">
                <rect x="0" y="0" width="400" height="400"/>
            </clipPath>
            <g id="chart-svg">
                <g id="svg-main" clip-path="url(#rect-mask-Main)">
                    <clipPath id="rect-mask-Main">
                        <rect x="0" y="0" width="400" height="400"/>
                    </clipPath>
                    <g id="Drawing-svg">
                        <g id="Parts-svg">
                            <g id="Section-svg">
                                <g id="Item1-svg">
                                    <path d="M 155.09357,45.542471 104.77897,86.931934 75,200 152.79121,141.87343 200,84.246354 Z" stroke="#e6e6e6" style="fill:#e6e6e6;stroke-width:0.3;stroke-linecap:round;stroke-linejoin:round" id="Item1"/>
                                </g>
                                <g id="Item2-svg">
                                    <path d="M 198.06872,89.614437 -9.21291,31.643703 -23.42303,34.67823 51.52002,20.68699 47.20879,-57.62707 z" stroke="#e6e6e6" style="fill:#e6e6e6;stroke-width:0.3;stroke-linecap:round;stroke-linejoin:round" id="Item2"/>
                                </g>
                                <g id="Item3-svg">
                                    <path d="M 161.0455,182.56778 -41.68122,-5.64443 15.98375,27.05111 67.62172,3.73783 32.80201,-13.55927 z" stroke="#e6e6e6" style="fill:#e6e6e6;stroke-width:0.3;stroke-linecap:round;stroke-linejoin:round" id="Item3"/>
                                </g>
                            </g>
                        </g>
                    </g>
                </g>
            </g>
        </g>
    </g>
</svg>
Oran G. Utan
  • 455
  • 1
  • 2
  • 10
  • Can your XSLT transformer really run javascript or any other scripting language? And even if it can does it have a layout engine to compute bounding boxes? – Robert Longson Oct 25 '22 at 22:31
  • @RobertLongson in the answer I linked from Dimitre Novatchev (https://stackoverflow.com/questions/7444317/how-to-include-javascript-file-in-xslt) I could understand that it would work if called by a VBA macro, so I would say so. – Oran G. Utan Oct 25 '22 at 22:34
  • That question is about including javascript in the XSLT transform output, not running it. – Robert Longson Oct 26 '22 at 07:49
  • For the record @Bradipo asked a related question about how to calculate the bounding box of a path and centre some text, but without involving JS: https://stackoverflow.com/questions/74211613/how-to-programmatically-center-text-boxes-to-parent-grouped-svg-paths-with-xslt/74223490 – Conal Tuohy Oct 28 '22 at 09:19

1 Answers1

0

If what you want is to centre the text, you can do this in pure SVG: https://stackoverflow.com/a/31522006/7372462

I don't think your plan to use a JavaScript function is practical, because you would need to pass the SVG itself to the JavaScript function which would need an actual browser rendering engine to evaluate it.

Conal Tuohy
  • 2,561
  • 1
  • 8
  • 15
  • I tried but unfortunately it did not work, the text goes all together in a part of the drawing. So from what I understand of your answer, Javascript would not actually give a value to be entered "for good", this would be dynamically calculated by a browser each time? – Oran G. Utan Oct 25 '22 at 23:23
  • 1
    To calculate the actual numeric values, the JS function would need to have an SVG rendering engine, font metrics, etc, i.e. it would need to be embedded in a browser which is displaying the SVG. A JS module called from an XSLT stylesheet as an extension function is not in that position, I think. But even if it could be made to work, it's an added complexity since you can centre text in SVG natively. – Conal Tuohy Oct 26 '22 at 00:48
  • Would you suggest I ask another question for this then? – Oran G. Utan Oct 26 '22 at 09:22
  • Yeah, I would, actually. Make sure to include the input SVG along with your XSLT. – Conal Tuohy Oct 26 '22 at 11:22