htmlcssclojureenlive

How to use selector negation (but ...) in Enlive on a more complex HTML snippet?


I have got an HTML snippet similar to:

<div id="root">
    <div id="A" attrib_2="bar"></div>
    <div id="B" attrib_2="baz">
        <div id="H" attrib_1="gnu">
            <p>
                <div id="F" attrib_2="baz"></div>
            </p>
        </div>
    </div>
    <div id="C" attrib_2="owl"></div>
    <div id="D" attrib_2="uhu"></div>
    <div id="E" attrib_2="boom"></div>
</div>

Now, I would like to select all snippets having an attrib_2 (*[attrb_2]) excluding those being descendants of a node having an attrib_1 set. There can be more nesting levels with arbitrary tags (like <p> in this example). With Enlive (http://enlive.cgrand.net/), I have already tried something like:

(select snippet [(but (attr? :attrib_1)) (attr? :attrib_2)])

But this doesn't work because the negation (but (attr? :attrib_1)) matches also the <p> tag. Is there a way to express this with the given selector predicates (http://enlive.cgrand.net/syntax.html), or do I have to write my own?

Thanks in advance

-Jochen


Solution

  • You have to write your own selector:

    (def parents 
      (zip-pred (fn [loc pred]
                  (some pred (take-while identity (iterate zip/up loc))))))
    

    (untested)

    and then

    (select snippet [[(attr? :attrib_2) (but (parents (attr? :attrib_1))]])
    

    should work.