web-dev-qa-db-fra.com

Analyse XML de Clojure

Je ne trouve aucune information sur la façon d'analyser les documents XML et d'accéder aux éléments.

J'ai trouvé deux façons d'analyser le document xml

(clojure.Zip/xml-Zip (clojure.xml/parse file))

et

(parse-seq file)

mais je peux trouver des informations sur la façon de traiter la structure résultante?

Le fichier source fait référence à Zip-query.clj sur la façon d'interroger le résultat, mais cela semble également manquer.

65
Hamza Yerlikaya

Supposons que vous ayez le xml suivant à analyser dans votre fichier:

<high-node>
   <low-node>my text</low-node>
</high-node>

vous chargez clojure.xml:

user=> (use 'clojure.xml)

une fois analysé, le xml aura la structure suivante:

{:tag :high-node, :attrs nil, :content [{:tag :low-node, :attrs nil, :content ["my text"]}]}

et vous pouvez ensuite sélectionner le contenu du fichier pour obtenir le contenu du low-node:

user=> (for [x (xml-seq 
              (parse (Java.io.File. file)))
                 :when (= :low-node (:tag x))]
         (first (:content x)))

("my text")

De même, si vous vouliez avoir accès à la liste complète des informations sur le nœud bas, vous changeriez le :when prédicat à (= (: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"]})

Cela fonctionne car les mots clés peuvent fonctionner comme des fonctions. Voir Questions sur les listes et autres choses dans Clojure et Structures de données: mots-clés

82
Pinochle

La réponse ci-dessus fonctionne, mais je la trouve beaucoup plus facile à utiliser clojure.data.Zip.xml (anciennement clojure-contrib.Zip-filter.xml avant Clojure 1.3).

fichier:

myfile.xml:

<songs>
  <track id="t1"><name>Track one</name></track>
  <track id="t2"><name>Track two</name></track>
</songs>

code:

; 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")

Malheureusement, vous devez tirer une dépendance sur data.Zip pour obtenir cette fonctionnalité de lecture/filtrage Nice. Ça vaut la dépendance:) Dans lein ce serait (au 17 août 2013):

[org.clojure/data.Zip "0.1.1"]

Et comme pour les documents pour data.Zip.xml ... Je regarde juste le fichier source relativement petit ici pour voir ce qui est possible. Un autre bon SO réponse ici , aussi.

56
overthink