How to use selector negation (but …) in Enlive on a more complex HTML snippet?
Frage
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 descendands of a node having 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 one?
Thanks in advance
-Jochen
Lösung
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.
Andere Tipps
#root #a attrib_2{}
#root #b attrib_2{}
#root #c attrib_2{}
#root #d attrib_2{}
#root #e attrib_2{}
that will select all attrib2 snippets in css inside the root div.
Just for argument sake, couldn't you do this:
<div id="whatever" class="attrib_2 bar"></div>
Semantically it seems like this would be better, but then again I don't know what systems you're using, or what your final purpose is. However, if you were to use classes, the CSS would be extremely simple:
div.attrib.bar {
something:else;
}