Comment puis-je combiner les résultats de requêtes zip-filtre sur un arbre XML dans Clojure?
-
20-09-2019 - |
Question
Je veux combiner les résultats de trois requêtes zip-filtre sur un arbre XML. Le XML J'analyse ressemble à ceci:
<someroot>
<publication>
<contributors>
<person_name>
<surname>Surname A</surname>
</person_name>
<person_name>
<given_name>Given B</given_name>
<surname>Surname B</surname>
<suffix>Suffix B</suffix>
</person_name>
</contributors>
</publication>
</someroot>
De cet exemple, vous pouvez voir que <given_name>
et <suffix>
sont facultatifs - seulement <surname>
est nécessaire. Ici, en voici mon problème - si je lance trois requêtes distinctes les réponses que je reçois seront en décalage avec l'autre:
(xml-> xml :publication :contributors :person_name :given_name text)
(xml-> xml :publication :contributors :person_name :surname text)
(xml-> xml :publication :contributors :person_name :suffix text)
Après avoir exécuté ces trois requêtes, je vais à gauche avec trois séquences dont cardinalités ne correspondent pas; given_name
et suffix
seront longueur 1 tandis que surname
sera longueur 2. Cela me rend impossible de combiner les composants de chaque nom. Je dois écrire une seule requête qui effectuera cette concaténation de nom lors de la construction de la séquence.
Je regarde la documentation très clairsemée pour clojure.contrib.zip-filter.xml
et ne peut pas comprendre comment je pouvais le faire (ou s'il est même possible). Malheureusement, je suis un Clojure (et Lisp) débutant! Quelqu'un peut-il indiquer comment je peux écrire une requête qui concaténer trois autres requêtes intégrées?
La solution
Vous pouvez obtenir toutes les personnes sous-arbres en une seule étape (xml-> xmlzip: publication: collaborateurs: person_name), puis obtenir les pièces de nom si elles existent (xml1-> personzip: texte de nom de famille) et les combiner au résultat que vous voulez comme ceci:
(use 'clojure.contrib.zip-filter.xml)
(defn format-name
[surname given suffix]
(str surname (if given (str ", " given)) (if suffix (str ", " suffix))))
(defn get-names
[xz]
(map (juxt
#(xml1-> % :surname text)
#(xml1-> % :given_name text)
#(xml1-> % :suffix text))
(xml-> xz :publication :contributors :person_name)))
(let [x (clojure.zip/xml-zip (clojure.xml/parse "foo.xml"))]
(map (partial apply format-name) (get-names x)))
Les résultats de ( "Nom A" "Nom B, B donné, le suffixe B")
Autres conseils
Je suppose une autre solution consiste à
(xml-> xml :publication :contributors :person_name)
puis traiter chaque <person_name>
plus tard.