2010-01-13 24 views
8

Quiero combinar los resultados de tres consultas de zip-filter en un árbol xml. El XML estoy de análisis es el siguiente:¿Cómo combino los resultados de las consultas de filtro zip en un árbol xml en Clojure?

<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 este ejemplo se puede ver que <given_name> y <suffix> son opcionales - Sólo se requiere <surname>. Aquí en yace mi problema - si me quedo tres consultas separadas las respuestas que recibo estarán fuera de orden entre sí:

(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) 

Después de ejecutar estas tres preguntas que se quedará con tres secuencias cuya cardinalidad no coinciden; given_name y suffix serán de longitud 1, mientras que surname tendrán una longitud de 2. Esto me impide combinar los componentes de cada nombre. Necesito escribir una sola consulta que realice esta concatenación de nombre durante la construcción de la secuencia.

Estoy viendo la documentación muy escasa para clojure.contrib.zip-filter.xml y no puedo entender cómo podría hacer esto (o si es posible). Lamentablemente, soy un novato Clojure (y Lisp). ¿Alguien puede señalar cómo puedo escribir una consulta que concatenará otras tres consultas integradas?

+1

Marque esta reciente así que la pregunta fuera: http://stackoverflow.com/questions/2034550/returning-multiple-values-using-clojure-xml-zipper –

Respuesta

6

Puede obtener todos los subárboles de persona en un paso (xml-> xmlzip: publicación: contribuidores: nombre_persona) luego obtener las partes de nombre si existen (xml1-> personzip: texto de apellido) y combinarlas con el resultado que quiere de este 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))) 

resultados en ("apellido A" "B apellido, dado B, sufijo B")

2

supongo una solución alternativa es

(xml-> xml :publication :contributors :person_name) 

y luego procesar cada <person_name> más adelante.

Cuestiones relacionadas