Como combino os resultados de consultas de filtro zip em uma árvore XML em Clojure?
-
20-09-2019 - |
Pergunta
Quero combinar os resultados de três consultas de filtro zip em uma árvore XML. O XML que eu estou analisando se parece com o seguinte:
<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>
A partir deste exemplo, você pode ver isso <given_name>
e <suffix>
são opcionais - apenas <surname>
É necessário. Aqui estão no meu problema - se eu executar três consultas separadas, as respostas que recebo ficarão fora de ordem uma com a outra:
(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)
Depois de executar essas três consultas, ficarei com três seqüências cujas cardinalidades não correspondem; given_name
e suffix
será de comprimento 1 enquanto surname
será o comprimento 2. Isso torna impossível combinar os componentes de cada nome. Preciso escrever uma única consulta que executará esse nome concatenação durante a construção de sequência.
Estou olhando para a documentação muito esparsa para clojure.contrib.zip-filter.xml
e não consigo descobrir como eu poderia fazer isso (ou se é possível). Infelizmente, sou um novato (e Lisp)! Alguém pode apontar como posso escrever uma consulta que concatenará três outras consultas incorporadas?
Solução
Você pode obter todas as subáridas de uma pessoa em uma etapa (xml-> xmlzip: Publicação: Colaboradores: Person_name), em seguida, obtenha as partes do nome se elas existirem (XML1-> Personzip: Sobrenome Texto) e combiná-las com o resultado que desejar:
(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)))
Resulta em ("Sobrenome A" "Sobrenome B, dado B, Sufixo B")
Outras dicas
Suponho que uma solução alternativa é
(xml-> xml :publication :contributors :person_name)
e então processe cada um <person_name>
mais tarde.