2013-01-18 152 views

回答

2

OK,這裏是我已經成功地放在一起的解決方案。它是用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. 條件跳過冷杉t節點返回(它總是遍歷根)
(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)))))