querySelector в Apache Batik

Я хотел бы запросить Apache Batik DOM для элементов, которые соответствуют селектору CSS.

Предоставляет ли Batik альтернативу любому из следующих методов DOM браузера?


person Brandon Bloom    schedule 18.01.2013    source источник


Ответы (1)


Хорошо, вот решение, которое мне удалось собрать. Он написан на Clojure, а не на Java, но важные моменты таковы:

  1. Создание экземпляра org.apache.batik.css.engine.sac.CSSConditionFactory
  2. Создать экземпляр org.apache.batik.css.parser.Parser
  3. Вызов Parser.parseSelectors
  4. Вызов org.apache.batik.dom.traversal.TraversalSupport.createNodeIterator
  5. В вашем NodeFilter выполните итерацию по проанализированному SelectorList, вызвав ExtendedSelector.match
  6. Условно пропустить первый узел, возвращенный итератором (это всегда корень обхода)
(def ^:private condition-factory
  (CSSConditionFactory. nil "class" nil "id"))

(defn- parse-selector [selector]
  (let [parser (Parser.)]
    (doto parser
      (.setSelectorFactory CSSSelectorFactory/INSTANCE)
      (.setConditionFactory condition-factory))
    (.parseSelectors parser selector)))

(defn- matches?
  ([selector element] (matches? selector element ""))
  ([selector element pseudo]
   (let [length (.getLength selector)]
     (loop [i 0]
       (if (< i length)
         (if (.. selector (item i) (match element pseudo))
           true
           (recur (inc i)))
         false)))))

(defn selection-seq [root selector]
  (let [selector (parse-selector selector)
        iterator (.createNodeIterator (TraversalSupport.)
                   (.getOwnerDocument root)
                   root
                   NodeFilter/SHOW_ELEMENT
                   (reify NodeFilter
                     (acceptNode [_ element]
                       (if (matches? selector element)
                         NodeFilter/FILTER_ACCEPT
                         NodeFilter/FILTER_REJECT)))
                   false)
        node-seq ((fn step []
                    (lazy-seq
                      (when-let [node (.nextNode iterator)]
                        (cons node (step))))))]
    ;; Iterator always returns the reference node, so match it.
    (when-let [node (first node-seq)]
      (if (matches? selector (first node-seq))
        node-seq
        (next node-seq)))))
person Brandon Bloom    schedule 18.01.2013