2017-10-03 3 views
0
(def testxml2 
"<top> 
    <group> 
     <group> 
      <item> 
       <number>1</number> 
      </item> 
      <item> 
       <number>2</number> 
      </item> 
      <item> 
       <number>3</number> 
      </item> 
     </group> 
     <item> 
      <number>0</number> 
     </item> 
    </group> 
</top>") 

(def txml2 (zip-str testxml2)) 

(defn deep-items [x] 
    (zip-xml/xml-> x 
     :top 
     :group 
     :group 
     :item)) 

(count (deep-items txml2)) 
;; 1 

(zip-xml/text (first (deep-items txml2))) 
;; "0" 

Ich versuche, den Wert der inneren :group zu bekommen, aber es scheint, auf der Außenseite eines erwischt zu werden. Es scheint zu ignorieren die zweite :group.Kann nicht tief verschachtelte XML mit clojure.data.zip.xml Zugriff

Das eigentliche XML, das ich zu analysieren versuche, hat ein wiederholtes verschachteltes <TheirTag><TheirTag>Foo</TheirTag></TheirTag> Muster und ich muss auf jeden Foo einzeln zugreifen. Das XML stammt von einer Drittpartei, daher kann ich das XML nicht einfach umstrukturieren, um dies zu vermeiden.

Antwort

1

The reason for the bug is here. Für die Kurzfassung: Die Version 0.1.2 ist insofern leicht gebrochen, als ein gleichnamiger Untereintrag über die tag=-Funktion (die den :myTag-Selektoren zugrunde liegt) nicht ausgewählt werden kann. Dies liegt an einer Regression von 0.1.1 zu 0.1.2 (dank @bpeter und @shilder). die Abhilfe ist eine Funktion tag= in einigem util-Namensraum zu machen und es direkt verwenden, bis die Regression festgelegt ist.

;; util.clj 
(defn tag= 
    "This is a workaround to a regression in 0.1.2. Fixed in upcoming 1.2.0 

    Returns a query predicate that matches a node when its is a tag 
    named tagname." 
    [tagname] 
    (fn [loc] 
    (filter #(and (zip/branch? %) (= tagname (:tag (zip/node %)))) 
     (zf/children-auto loc)))) 

;; project.somefile.clj 
(ns project.somefile 
    (:require [project.util :as u])) 


(defn deep-items [x] 
    (zip-xml/xml-> x 
     :top 
     (u/tag= :group) 
     (u/tag= :group) 
     :item)) 
1

du the Tupelo Forest library mit lösen zu verarbeiten Baum-ähnliche Datenstrukturen.Neben der expliziten Suche kann es auch Wildcards wie zsh. Documentation is ongoing verwenden, aber das wird Ihnen einen Vorgeschmack geben, was Sie tun können:

(dotest 
    (with-forest (new-forest) 
    (let [xml-str   "<top> 
           <group> 
            <group> 
             <item> 
              <number>1</number> 
             </item> 
             <item> 
              <number>2</number> 
             </item> 
             <item> 
              <number>3</number> 
             </item> 
            </group> 
            <item> 
             <number>0</number> 
            </item> 
           </group> 
          </top>" 

      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 fn-blank-leaf-hid? ; whitespace pred fn 
          [hid] 
          (let [node (hid->node hid)] 
           (and (contains-key? node :value) 
           (ts/whitespace? (grab :value node))))) 
      blank-leaf-hids (keep-if blank-leaf-hid? (all-leaf-hids)) ; find whitespace nodes 
      >>    (apply remove-hid blank-leaf-hids) ; delete whitespace nodes found 

Der Teil, um den Sie sich wirklich kümmern, ist hier. Es gibt zwei Möglichkeiten, nach verschachtelten Knoten zu suchen.

  1. Die erste Methode spezifiziert einen expliziten Pfad von der Wurzel
  2. der zweite ein Wildcard :** wie zsh verwendet, die keine oder mehrere Verzeichnisse übereinstimmt.

     ; Can search for inner `div` 2 ways 
         result-1  (find-paths root-hid [:top :group :group]) ; explicit path from root 
         result-2  (find-paths root-hid [:** :group :item :number]) ; wildcard path that ends in :number 
         ] 
    

    Für Guss- (1), sehen wir, dass wir nur die Artikel 1, 2 und 3 gefunden:

    ; Here we see only the double-nested items 1, 2, 3 
        (is= (spyx-pretty (format-paths result-1)) 
        [[{:tag :top} 
         [{:tag :group} 
         [{:tag :group} 
         [{:tag :item} [{:tag :number, :value "1"}]] 
         [{:tag :item} [{:tag :number, :value "2"}]] 
         [{:tag :item} [{:tag :number, :value "3"}]]]]]]) 
    

Für den Fall (2), fanden wir nicht nur die doppelt verschachtelten Artikel, sondern auch die einzeln verschachtelte Artikel 0:

 ; Here we see both the double-nested items & the single-nested item 0 
     (is= (spyx-pretty (format-paths result-2)) 
     [[{:tag :top} 
      [{:tag :group} [{:tag :item} [{:tag :number, :value "0"}]]]] 
     [{:tag :top} 
      [{:tag :group} 
      [{:tag :group} [{:tag :item} [{:tag :number, :value "1"}]]]]] 
     [{:tag :top} 
      [{:tag :group} 
      [{:tag :group} [{:tag :item} [{:tag :number, :value "2"}]]]]] 
     [{:tag :top} 
      [{:tag :group} 
      [{:tag :group} [{:tag :item} [{:tag :number, :value "3"}]]]]]]) 

    ))) 

Sie nicht angeben, was man benötigt Downstream Processing. Tupelo.Forest ist in der Lage, Ausgabe in beide hiccup und enlive Formate zu konvertieren, und es ist eigene hiccup-inspirierte bush Format und eine belebende inspirierte tree Format.

+0

Upvoted für wirklich coole Bibliothek (Lesezeichen!). Leider habe ich schon fast das gesamte Projekt mit zip-xml ausgeschrieben und die Pferde an dieser Stelle zu wechseln wäre eine Qual. Danke, dass Sie sich die Zeit genommen haben, diese Beispiele zu teilen! – BWStearns

Verwandte Themen