Clojure XML Parsing
clojure-contrib (2)
No puedo encontrar ninguna información sobre cómo analizar documentos xml y acceder a elementos.
He encontrado dos formas de analizar el documento xml
(clojure.zip/xml-zip (clojure.xml/parse file))
y
(parse-seq file)
pero parece que puedo encontrar información sobre cómo procesar la estructura resultante?
El archivo de origen hace referencia a zip-query.clj sobre cómo consultar el resultado, pero parece que también falta.
La respuesta anterior funciona, pero me resulta mucho más fácil usar clojure.data.zip.xml
(solía ser clojure-contrib.zip-filter.xml
antes de Clojure 1.3).
archivo:
myfile.xml
:
<songs>
<track id="t1"><name>Track one</name></track>
<track id="t2"><name>Track two</name></track>
</songs>
código:
; Clojure 1.3
(ns example
(:use [clojure.data.zip.xml :only (attr text xml->)]) ; dep: see below
(:require [clojure.xml :as xml]
[clojure.zip :as zip]))
(def xml (xml/parse "myfile.xml"))
(def zipped (zip/xml-zip xml))
(xml-> zipped :track :name text) ; ("Track one" "Track two")
(xml-> zipped :track (attr :id)) ; ("t1" "t2")
Desafortunadamente, necesita establecer una dependencia en data.zip para obtener esta buena funcionalidad de lectura / filtro. Vale la pena la dependencia :) En lein sería (desde el 17 de agosto de 2013):
[org.clojure/data.zip "0.1.1"]
Y en cuanto a los documentos para data.zip.xml
... simplemente miro el archivo fuente relativamente pequeño here para ver qué es posible. Otra buena respuesta SO here , también.
Supongamos que tiene el siguiente xml para analizar en su archivo:
<high-node>
<low-node>my text</low-node>
</high-node>
carga clojure.xml
:
user=> (use ''clojure.xml)
cuando se analiza, el xml tendrá la siguiente estructura:
{:tag :high-node, :attrs nil, :content [{:tag :low-node, :attrs nil, :content ["my text"]}]}
y luego puede buscar el contenido del archivo para obtener el contenido de los low-node
:
user=> (for [x (xml-seq
(parse (java.io.File. file)))
:when (= :low-node (:tag x))]
(first (:content x)))
("my text")
Del mismo modo, si quisiera tener acceso a toda la lista de información en low-node, cambiaría :when
predicate to (= (:high-node (:tag x)))
:
user=> (for [x (xml-seq
(parse (java.io.File. file)))
:when (= :high-node (:tag x))]
(first (:content x)))
({:tag :low-node, :attrs nil, :content ["my text"]})
Esto funciona porque las palabras clave pueden funcionar como funciones. Consulte Preguntas sobre listas y otras cosas en Clojure y Data Structures: palabras clave