off-topic

https://github.com/clojurians/community-development/blob/master/Code-of-Conduct.md Clojurians Slack Community Code of Conduct. Searchable message archives are at https://clojurians-log.clojureverse.org/
tvaughan 2021-04-21T12:27:21.292Z

Does anyone know of a tool like https://github.com/svg/svgo but in Java or Clojure? I want to be able to "normalize" svg drawings into some sort of common denominator, e.g. apply transformations to paths. There's no dom or gui involved, so just xml in and xml out

flowthing 2021-04-21T12:40:55.292300Z

XSLT?

tvaughan 2021-04-21T12:58:42.292500Z

This https://stackoverflow.com/a/15113751 is an example of some of the calculations that need to be done. From what I remember, I don't think xslt can do this, right? It's been years since I've worked with xslt

flowthing 2021-04-21T14:32:48.293Z

There's quite a lot behind that SO link so I'm not sure what exactly you mean. Do you mean transforming matrix(...)? You could do it with XPath 2.0, at least. (Shameless plug: https://github.com/eerohele/sigel)

tvaughan 2021-04-21T14:45:43.293400Z

I mean I need to be able to do something like:

# cat example.svg
<g transform="matrix(0.443,0.896,-0.896,0.443,589.739,-373.223)">
    <path d="M486,313s27-9,43-29l26,4,1,23-22,5s-25-6-48-3z" />
</g>
# svgo example.svg -o -
<g><path d="M524.589 200.892s20.025 20.205 45.033 25.681l7.934 25.068-20.165 11.085-14.226-17.497s-5.699-25.058-18.576-44.337z"/></g>
according to the calculation rules in the stackoverflow link

tvaughan 2021-04-21T14:48:47.293700Z

Thanks for the pointer to sigel. This looks like it could be useful for working with the normalized svg

flowthing 2021-04-21T14:49:44.294Z

Right, I won't delve into the specifics of the calculation rules, but here's an example stylesheet that parses the matrix(...) values as floats and multiplies them by four:

&lt;xsl:stylesheet version="3.0" xmlns:xsl="<http://www.w3.org/1999/XSL/Transform>" xmlns:xs="<http://www.w3.org/2001/XMLSchema>"&gt;
    &lt;xsl:template match="g"&gt;
      &lt;g&gt;
        &lt;xsl:variable name="m"
          select="
            for-each(tokenize(substring-before(substring-after(@transform, '('), ')'), ','), xs:float#1)
          " as="xs:float*"/&gt;

        &lt;xsl:for-each select="$m"&gt;
          &lt;m&gt;&lt;xsl:value-of select=". * 4"/&gt;&lt;/m&gt;
        &lt;/xsl:for-each&gt;
      &lt;/g&gt;
    &lt;/xsl:template&gt;
&lt;/xsl:stylesheet&gt;

flowthing 2021-04-21T14:50:03.294200Z

Given that input, it produces:

λ saxon -xsl:stylesheet.xsl -s:input.xml | xmllint --format -
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;g xmlns:xs="<http://www.w3.org/2001/XMLSchema>"&gt;
  &lt;m&gt;1.772&lt;/m&gt;
  &lt;m&gt;3.584&lt;/m&gt;
  &lt;m&gt;-3.584&lt;/m&gt;
  &lt;m&gt;1.772&lt;/m&gt;
  &lt;m&gt;2358.956&lt;/m&gt;
  &lt;m&gt;-1492.892&lt;/m&gt;
&lt;/g&gt;

flowthing 2021-04-21T14:50:43.294400Z

That's just to illustrate that I think you can do that with XSLT & XPath. Whether you want to is another matter, of course. 🙂

tvaughan 2021-04-21T14:50:44.294600Z

That's very interesting! Thanks for the example

flowthing 2021-04-21T14:53:41.294800Z

A full-fledged parser for possible values of the transform attribute is another matter, of course. If that's mainly what you need to do, XSLT probably isn't very useful. Perhaps you could use XPath to reach into the values, hand them to a Clojure function that parses and transforms them, then sticks them into an output XML tree. Or something along those lines.

tvaughan 2021-04-21T15:21:59.295Z

Right, I see how xslt and xpath could be very helpful if I choose to roll my own. I hadn't thought to use them this way. Thanks for the suggestion!

flowthing 2021-04-21T15:23:44.295200Z

Sure. An additional thing to consider is using a combination of XSLT and Java/Clojure using integrated extension functions: https://cljdoc.org/d/me.flowthing/sigel/1.0.1/api/sigel.extension Essentially, you can define a Clojure function you call from your XSLT stylesheet.

flowthing 2021-04-21T15:25:23.295500Z

That is, you could write the attribute value parser in Clojure (maybe with Instaparse?) and use XSLT for transforming the XML tree.

1
tvaughan 2021-04-21T15:47:48.295800Z

Thanks again @flowthing

phronmophobic 2021-04-21T19:42:12.296600Z

Yea, I'm sure it's doable with a rules engine, but I'm not sure what the best way to leverage the rules engine would be. In my head, the approach would be something like: 1. write normal UI components and use general data access 2. have a way to automatically convert your UI to leverage the RETE algorithm for performance