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"

我试图获得内部的价值:group,但它似乎被外部的价值所吸引。似乎忽略了第二个:group

我试图解析的实际 XML 有一个重复的嵌套<TheirTag><TheirTag>Foo</TheirTag></TheirTag>模式,我需要单独访问每个 Foo。XML 来自第三方,所以我不能只是重组 XML 来避免这种情况。

4

2 回答 2

1

该错误的原因在这里。对于简短版本:0.1.2 版本在这方面略有破坏,无法通过该tag=函数选择具有相同名称的子条目(这是:myTag样式选择器的基础。这是由于从 0.1.1 到 0.1 的回归.2(感谢@bpeter 和@shilder)。解决方法是tag=在某个 util 命名空间中创建一个函数并直接使用它,直到修复回归。

;; 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))
于 2017-10-03T04:49:13.257 回答
0

您可以使用Tupelo Forest 库处理树状数据结构来解决此问题。除了显式搜索,它还可以使用通配符,如zsh. 文档正在进行中,但这将使您了解您可以做什么:

(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

你真正关心的部分在这里。有两种方法可以搜索嵌套节点。

  1. 第一种方法指定从根开始的显式路径
  2. 第二个使用:**像 zsh 这样的通配符,它​​匹配零个或多个目录。

          ; 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
          ]
    

    对于 cast (1),我们看到我们只找到了项目 1、2 和 3:

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

对于情况(2),我们不仅找到了双重嵌套项,还找到了单嵌套项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"}]]]]]])

      )))

您没有指定所需的下游处理。Tupelo.Forest能够将输出转换为hiccupenlive格式,加上它自己的打嗝式bush格式和生动的tree格式。

于 2017-10-03T06:16:48.343 回答