2016-09-18 5 views
1

나는 html/xml 데이터 구조를 걷고있다. 나는 clojure.zip을 사용하여 그것을 걸어 간다. cut (가지 치기)를 원하는 노드를 찾으면 모든 자식 노드와 오른쪽 노드를 제거 할 수있는 방법을 찾을 수 없습니다.Clojure XML 지퍼 워크 및 자두

예 :

의 내가이 나무 있다고 가정 해 봅시다 (즉, HTML을 나타냄) :

(def tree [:p "F" 
      [:p "G" [:p "I" [:p "H"]]] 
      [:p "B" 
      [:p 
      "D" 
      [:p "E"] 
      [:p "C"]] 
      [:p "A"]]]) 

내가 xml-zip 그것을, 그것을 분석하고, 어떤 시점에서 내가 노드에 결국 걷는 동안 " D ", 내가 자르고 싶은 곳. 이제 "E", "C"(어린이) 및 "D"없이 루트를 반환해야합니다. 이것들은이 시점에서 next을 사용할 때 이미 방문하지 않은 모든 노드입니다.

어떻게 이러한 노드를 제거합니까?

참고 : 가능하지 않은 경우 지퍼를 cut 지점까지 복사하는 방법을 환영합니다.

예 데이터 : 그리고이 같은 내용을 얻기 위해 그것을 통해 걷고

{:tag :html, :attrs nil, :content [{:tag :head, :attrs nil, :content nil} {:tag :body, :attrs nil, :content [{:tag :p, :attrs nil, :content ["F"]} {:tag :p, :attrs nil, :content ["G"]} {:tag :p, :attrs nil, :content ["I"]} {:tag :p, :attrs nil, :content ["H"]} {:tag :p, :attrs nil, :content nil} {:tag :p, :attrs nil, :content nil} {:tag :p, :attrs nil, :content ["B"]} {:tag :p, :attrs nil, :content ["D"]} {:tag :p, :attrs nil, :content ["E"]} {:tag :p, :attrs nil, :content ["C"]} {:tag :p, :attrs nil, :content nil} {:tag :p, :attrs nil, :content ["A"]} {:tag :p, :attrs nil, :content nil} {:tag :p, :attrs nil, :content nil}]}]} 

시작 : 이것은 내가 xml-zip를 호출하는 내가 위의 나무에 대한이 분석 된 데이터입니다

(-> parsed (z/xml-zip) 
      (z/down) ;head 
      (z/right) ; body 
      (z/down) ; content 
      ) 

또 다른 예 :

다음 문자열 : "<article><h1><img href=\"some-url\"></img> some-text <b>in bold</b></h1><ul><li> AA </li> <li>BB</li></ul></article>" 나에게 다음지도 줄 것이다 :

[{:tag :html, :attrs nil, :content [{:tag :head, :attrs nil, :content nil} {:tag :body, :attrs nil, :content [{:tag :article, :attrs nil, :content [{:tag :h1, :attrs nil, :content [{:tag :img, :attrs {:href "some-url"}, :content nil} " some-text " {:tag :b, :attrs nil, :content ["in bold"]}]} {:tag :ul, :attrs nil, :content [{:tag :li, :attrs nil, :content [" AA "]} " " {:tag :li, :attrs nil, :content ["BB"]}]}]}]}]} nil] 

는 "일부 텍스트"에서 절단 궁극적으로 모든 <article><h1><img href=\"some-url\"></img> some-text</h1></article>

+0

당신은 노드와 관련된 하위 트리를 제거 https://clojuredocs.org/clojure.zip/remove을 사용할 수 있습니다 그것으로. – Grav

+0

@Grav는 노드를 제거하지만 그 노드와 연관된 하위 트리를 제거하지는 않습니다. – nha

+0

(그리고 그랬더라도 내 예제에서 A는 D의 하위 트리에 속하지 않습니다.) – nha

답변

2

전나무, 난 당신의 작업을 다음과 같은 방법을 바꿔 것 문자열 발생한다 :

목표는 노드를 찾아서 그 오른쪽에서 모든 노드를 제거하는 것입니다. 부모입니다. 새 노드를 만들고,이 위에 말한대로

(defn cut [loc] 
    (when-let [parent (z/up loc)] 
    (z/edit parent #(z/make-node loc % (z/lefts loc))))) 

그래서, 우리는 loc의 부모를 편집 :

이런 식으로 말하면

cut 기능은 쉽게 부모 clojure.zip/edit의 도움으로 구현 될 수 그 중 아이들 만 loc의 왼쪽에 두십시오.

: 전달 된 위치는 부모가없는 경우 널 포인터 예외를 방지하기 위해 when-let 매크로 거기 있다는 것을

통지, 시험 이제

(는 지퍼의 루트 의미)

의이 p["I"] 포함 삭제하려고하자 :

user> (-> html 
      z/xml-zip 
      z/down 
      z/right 
      z/down 
      z/right 
      z/right 
      z/node) 
;; {:tag :p, :attrs nil, :content ["I"]} 

user> (-> html 
      z/xml-zip 
      z/down 
      z/right 
      z/down 
      z/right 
      z/right 
      cut 
      z/root) 
;;{:tag :html, :attrs nil, 
;; :content [{:tag :head, :attrs nil, :content nil} 
;;   {:tag :body, :attrs nil, 
;;   :content [{:tag :p, :attrs nil, :content ["F"]} 
;;      {:tag :p, :attrs nil, :content ["G"]}]}]} 

기대로 :에서 오른쪽으로 모든 것을 (포함) I이 몸에서 제거되었습니다.

갱신

업데이트에 따라, 당신은 목표 한 후 트리 의 모든 노드를 제거합니다. 모든 노드의 부모를 루트로 변경해야하므로 조금 더 까다 롭습니다. 이 경우 cut 기능은 다음과 같을 수 있습니다 :

(defn cut [loc] 
    (loop [loc loc] 
    (if-let [parent (z/up loc)] 
     (recur 
     (z/replace parent 
        (z/make-node loc 
           (z/node parent) 
           (drop-last (count (z/rights loc)) 
              (z/children parent))))) 
     (z/node loc)))) 

시험 :

user> (-> h2 
      z/xml-zip 
      z/down 
      z/right 
      z/down 
      z/down 
      z/down 
      z/right 
      cut) 

;;{:tag :html, :attrs nil, 
;; :content [{:tag :head, :attrs nil, :content nil} 
;;   {:tag :body, :attrs nil, 
;;   :content [{:tag :article, :attrs nil, 
;;      :content [{:tag :h1, :attrs nil, 
;;         :content [{:tag :img, :attrs {:href "some-url"}, :content nil} " some-text "]}]}]}]} 
+0

오늘 저녁 자세히 보았지만 괜찮습니다. 감사합니다! > HTML 우편/zml 지퍼 우편/아래 우편/우 우편/아래 우편/아래 -''' (: – nha

+0

나는 작동하지 않는 것 (내 편집 질문에) 또 다른 예에 그것을 시도 zip/down zip/right 컷 zip/root) ;; AA와 BB는 아직도 거기에있다.''' – nha

+0

하지만'AA'와'BB'는'some-text'의 부모 노드 ('h1')의 자식이 아니며 부모의 형제 자매입니다. – leetwinski