Come faccio a combinare i risultati di query zip-filtro su un albero XML in Clojure?
-
20-09-2019 - |
Domanda
Voglio combinare i risultati di tre interrogazioni zip-filtro su un albero XML. L'XML sto parsing assomiglia a questo:
<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>
Da questo esempio si può vedere che <given_name>
e <suffix>
sono opzionali - è richiesto solo <surname>
. Qui giace nel mio problema - se corro tre query separate le risposte che ottengo sarà fuori forma con l'altro:
(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)
Dopo l'esecuzione di queste tre domande sarò lasciato con tre sequenze la cui cardinalità non corrispondono; given_name
e suffix
saranno lunghezza 1 mentre surname
sarà lunghezza 2. Questo rende impossibile per me per combinare i componenti di ogni nome. Ho bisogno di scrivere una singola query che eseguirà questo nome concatenazione durante la costruzione della sequenza.
Sto guardando la documentazione molto scarsa per clojure.contrib.zip-filter.xml
e non riesco a capire come avrei potuto fare questo (o se è ancora possibile). Purtroppo io sono un Clojure (e Lisp) newbie! Chiunque può segnalare come posso scrivere una query che concatenare altre tre domande incorporati?
Soluzione
È possibile ottenere tutte le sottostrutture persona in un solo passaggio (XML> xmlzip: pubblicazione: contributori: PERSON_NAME) quindi ottenere le parti di nome, se esistono (xml1-> personzip: il cognome del testo) e combinarli al risultato che si desidera in questo modo:
(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)))
Risultati in ( "Cognome A" "B Cognome, Data B, suffisso B")
Altri suggerimenti
Credo che una soluzione alternativa è quella di
(xml-> xml :publication :contributors :person_name)
e quindi elaborare ogni <person_name>
in seguito.