2017-06-20 8 views
2

私はxml->非常に混乱しているのを発見しました。私は、ドキュメントとサンプルを読んだが、XMLドキュメントのネストされたノードを取得する方法を理解することはできません。clojure.data.zipでxml->を使用してネストされたノードを取得する方法は?

次のXMLは、(XML-ZIPからのような)ジッパーであると仮定します

<html> 
<body> 
    <div class='one'> 
    <div class='two'></div> 
    </div> 
</body> 
</html> 

私はクラス= '2' でのdivを返すようにしようとしています。

私は仕事にこれを期待していた。

(xml-> z :html :body :div :div) 

またはこの:CSSセレクタのようなの

(xml-> z :html :body :div (attr= :class "two")) 

種類。

しかし、最初のレベルのみを返し、ツリーを検索しません。

私はそれを動作させることができる唯一の方法は次のとおりです。

(xml-> z :html :body :div children leftmost?) 

私が行うことになってるどんなことですか?

私がxml->を使い始めた全理由は、利便性とジッパーの上下左右の移動を避けるためです。 xml->ネストされたノードを取得できない場合、clojure.zipよりも値が表示されません。

ありがとうございました。

答えて

0

結果的に2つの:divが同じノードに一致します。あなたは降りてきたはずです。 そして、私はあなたがzip/nodeでノードを取得することを忘れてしまったと信じています。

(ns reagenttest.sample 
    (:require 
       [clojure.zip :as zip] 
       [clojure.data.zip.xml :as data-zip])) 
(let [s "..." 
     doc (xml/parse (java.io.ByteArrayInputStream. (.getBytes s)))] 
(prn (data-zip/xml-> (zip/xml-zip doc) :html :body :div zip/down (data-zip/attr= :class "two") zip/node))) 

またはあなたがxml->に満足できない場合は、カスタムメイドの抽象化を使用することができます。

(defn xml->find [loc & path] 
    (let [new-path (conj (vec (butlast (interleave path (repeat zip/down)))) zip/node)] 
     (apply (partial data-zip/xml-> loc) new-path))) 

今、あなたはこれを行うことができます:

(xml->find z :html :body :div :div) 
(xml->find z :html :body :div (data-zip/attr= :class "two")) 
+0

私がzip/downで持っている問題は、私が子供を使って持っているのと同じ問題です:div。それは漏れた抽象です。タグのセマンティクス、つまり(xml-> z:html:body:div [2] text)かそれに類するものを表現できるようにしたい。ジッパーをたどると、時にはタグが混乱して読みづらいことがあります。 (xml->:html:body)の代わりに(xml->:htmlの左端の子ですか?) – Scott

+1

私はこれまで、xml-seqを使ってコードを取得していました。思考xml->ははるかに簡単です。しかし、実際にはもっと複雑で、この不一致によって、xml-seqに戻ってしまいます。 – Scott

+0

これに関する私の更新を見てください。 – akond

1

をあなたはtupelo.forestを使用してこの問題を解決することができますfrom the Tupelo libraryforestには、データツリーを検索および操作するための関数が含まれています。それはステロイドでのEnliveのようなものです。

(dotest 
    (with-forest (new-forest) 
    (let [xml-str   "<html> 
          <body> 
           <div class='one'> 
           <div class='two'></div> 
           </div> 
          </body> 
          </html>" 

      enlive-tree  (->> xml-str 
          java.io.StringReader. 
          en-html/xml-resource 
          only) 
      root-hid  (add-tree-enlive enlive-tree) 

      ; Removing whitespace nodes is optional; just done to keep things neat 
      blank-leaf-hid? (fn [hid] (ts/whitespace? (hid->value hid))) ; whitespace pred fn 
      blank-leaf-hids (keep-if blank-leaf-hid? (all-leaf-hids)) ; find whitespace nodes 
      >>    (apply remove-hid blank-leaf-hids) ; delete whitespace nodes found 

      ; Can search for inner `div` 2 ways 
      result-1  (find-paths root-hid [:html :body :div :div]) ; explicit path from root 
      result-2  (find-paths root-hid [:** {:class "two"}]) ; wildcard path that ends in :class "two" 
    ] 
     (is= result-1 result-2) ; both searches return the same path 
     (is= (hid->bush root-hid) 
     [{:tag :html} 
      [{:tag :body} 
      [{:class "one", :tag :div} 
      [{:class "two", :tag :div}]]]]) 
     (is= 
     (format-paths result-1) 
     (format-paths result-2) 
     [[{:tag :html} 
      [{:tag :body} 
      [{:class "one", :tag :div} 
      [{:class "two", :tag :div}]]]]]) 

     (is (val= (hid->elem (last (only result-1))) 
      {:attrs {:class "two", :tag :div}, :kids []}))))) 

は多くの例があるin the unit teststhe forest-examples demo fileに:ここではあなたのデータのためのソリューションです。

関連する問題