This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-04-04
Channels
- # announcements (1)
- # babashka (7)
- # beginners (25)
- # calva (38)
- # cider (2)
- # clerk (54)
- # clojure (21)
- # clojure-austin (1)
- # clojure-europe (11)
- # clojure-nl (1)
- # clojure-norway (5)
- # clojure-uk (2)
- # clr (16)
- # conjure (2)
- # cursive (15)
- # datalevin (1)
- # datomic (2)
- # emacs (3)
- # fulcro (1)
- # hoplon (14)
- # humbleui (9)
- # hyperfiddle (31)
- # improve-getting-started (12)
- # jobs (7)
- # off-topic (15)
- # reitit (3)
- # releases (1)
- # spacemacs (22)
- # squint (16)
- # tools-deps (8)
- # vim (50)
- # xtdb (33)
Just started using zippers with XML. There's no way for a navigation to preserve grouping, is there? As a concrete example, suppose I have:
<item><type>a</type><value>b</value></item>
<item><type>x</type><value>y</value></item>
I can easily extract all types, all values, or both by using (zip.xml/xml-> item-zipper :type zip/node)
or some variation of it.
In the end, I need to have a collection of maps, like [{:type "a" :value "b"} {:type "x" :type "y"}]
.
Seems like I have to extract items as nodes, and then map over them with a function that converts its argument to a zipper and extracts the right text values. Is there no simpler approach?I've never used zip.xml. What I usually do is use https://grishaev.me/en/zippo/ or something similar. Basically, I would use zippo/loc-find-all
to locate all the items and then use zippo/loc-find
on each item to find the type and value.
I'm not sure how much you can assume about the xml you're consuming, but I've also had success mixing and matching zippers with meander.
The structure is fixed so I can assume everything. In this context, sounds like zippo
won't actually bring anything new to the table.
I briefly thought about using Specter for it, but decided against it as trying to remember and make sense of its grammar doesn't make me too enthusiastic.
It seems like you can just reduce over the children of the item
element. Each child tag is just a key value pair that you can dump into a map.
Yea, zippo
is more useful when you can't make as many assumptions about data. It's great for html parsing where you want to find the title and href for each container element somewhere inside the html.
(->> zitem
(z/children)
(into {}
(map (fn [node]
[(:tag node) (-> node :content first)]))))
I should've added - the items have more nodes than I need. :) So I'll end up filtering as well, and it'll end up being more code than with a zipper->nodes->zippers->nodes chain.
The question is more about zippers themselves rather than about how to do it in general.
in that case, zippo/loc-find
or zippo/loc-find-all
should be helpful for finding the relevant children of each item element.
But that's what that :type
already does in zip.xml/xml->
.
But I just discovered that I don't need to call zip/node
to get an item because instead I should be iterating over already existing zippers, the ones that (zip.xml/xml-> ... :item)
returns. So the chain becomes one link shorter.
I didn't really grok zippers until I read this article by my former team mate https://grishaev.me/en/clojure-zippers/ He makes the point in that article that zippers sweet spot is when you're trying to process docs where the structure is unknown ahead of time
However, zippers shine in the case where you must modify the tree. For the given goal, you could use xml-seq! Filter by #(= :item (:type %)). Then map to transform each <item> to a record, again using xml-seq unless some of them have child elements.
https://github.com/mudge/riveted
I think Riveted might be your best bet rather than zippers for this problem. You can search for each of your <item>
elements, and it returns a lazy sequence of navigator objects that can then be transformed into your desired format.
I used it recently to solve a similar-ish problem and it was both extremely easy to use and highly performant - even my extremely unoptimized code was able to process a lot of complex XML very quickly
zippers are really good for some problems, but I personally have trouble keeping track of "where" I am in the tree when thinking about, writing and testing them, which is particularly burdensome if the XML you're working with has a complex internal structure. the XPath navigation in riveted makes the simple stuff simple while still enabling the more complex stuff.
Just to follow up on this, did you read https://blog.korny.info/2014/03/08/xml-for-fun-and-profit.html#zippers - particularly the way he navigates into the parsed XML and then uses zippers on a per node basis? I copied this and it didn’t feel like too much work once I understood.
@UFTRLDZEW Thanks for pointing me to Riveted! It's 10x faster than zippers in my use-cases (not even mentioning Xalan, which is atrociously slow, at least when it comes to XPaths).
Hi all, I’m looking for a clojure/clojurescript crypto solution. I want to encrypt a payload with a public key in the browser, then decrypt it on the server. I found the javascript browser namespace for the Web Crypto API, and I have been using buddy on the server for a while now. But I cannot seem to find an asymmetric scheme that works in both places. Specifically, the Web Crypto API says the RSA-OAEP is the only asymmetric scheme for encryption (vs sign, etc) and even though buddy has a large number of RSA variations, none seem to correspond to RSA-OAEP. Any suggestions? I’m open to options outside of buddy and the web api, but I’d prefer not to import a library just for this functionality.
It does seem to be in the Buddy's source code: https://github.com/funcool/buddy-sign/blob/c1c7ffcd4b49d3604916736d15f03893e15e5814/src/buddy/sign/jwe/cek.clj#L38
oh interesting… let me take a look
And some examples in the docs, but not sure how relevant they are to your usecase. https://github.com/funcool/buddy-auth/blob/88b3ac08e2b3984158a359908344f87109a6a2a7/doc/user-guide.md#encrypted-jwt
Ah, that’s in buddy-sign… I wouldn’t have thought to look there