web-dev-qa-db-ja.com

Clojure XML解析

Xmlドキュメントを解析して要素にアクセスする方法に関する情報が見つかりません。

XMLドキュメントを解析する2つの方法を見つけました

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

そして

(parse-seq file)

しかし、結果の構造を処理する方法に関する情報を見つけることができますか?

ソースファイルは、結果をクエリする方法についてZip-query.cljを参照していますが、これも不足しているようです。

65
Hamza Yerlikaya

ファイルで解析する次のxmlがあるとします。

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

あなたはclojure.xmlをロードします:

user=> (use 'clojure.xml)

解析すると、xmlは次の構造になります。

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

次に、ファイルのコンテンツをシーケンス処理して、low-nodeのコンテンツを取得できます。

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

("my text")

同様に、下位ノードの情報のリスト全体にアクセスしたい場合は、:when述語を(= (: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"]})

これは、キーワードが関数として機能できるため機能します。 Clojureのリストおよびその他のものに関する質問 および データ構造:キーワード を参照してください

82
Pinochle

上記の答えは機能しますが、clojure.data.Zip.xmlを使用する方がずっと簡単です(以前はClojure 1.3より前はclojure-contrib.Zip-filter.xmlでした)。

ファイル:

myfile.xml

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

コード:

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

残念ながら、このナイスな読み取り/フィルター機能を使用するには、 data.Zip への依存関係を取り込む必要があります。 依存する価値があります:)lein の場合(2013年8月17日現在):

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

そしてdata.Zip.xmlのドキュメントについては...比較的小さなソースファイル here を見て、何が可能かを調べます。別の良いSO答え ここ も。

56
overthink