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

3

16

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

Absolute answered 10/8, 2011 at 20:3 Comment(4)
Semantically, should the inner attrib_2 be something different? [Edit: sorry, I was thinking about classes, which might actually be useful to identify the different scopes as opposed to attributes.]Dyslalia
The use case for this is to extract RDFa elements from a web page as described in w3.org/TR/rdfa-api. I want to search for "property" attributes within a tag having a "typeof" attribute. But only the "direct" descendants. An descendant with a "typeof" attribute opens a new context to be evaluated.Absolute
Why exactly did you tag this CSS? I'm not too familiar with Enlive, but if you are trying to achieve this solution in pure CSS, it is possible.Lody
I tagged this with CSS because Enlive uses the same selector semantics. How do you achieve this in pure CSS?Absolute
B
4

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.

Broderic answered 7/10, 2011 at 11:0 Comment(2)
If you want to traverse parents only, you should use (iterate zip/up (zip/up loc)) in predicate definition.Affiliate
Note that zip-pred now takes a 1-arity function, so pred should be made into an argument to parents.Irreconcilable
F
1
#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.

Freakish answered 29/8, 2011 at 0:1 Comment(0)
T
1

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;
}
Toot answered 13/10, 2011 at 17:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.