选择器的工作方式与/ deep /类似

时间:2018-04-22 00:08:49

标签: css xpath css-selectors

我需要一个选择器来选择X类中的所有内容,但Y类对象除外。也许我的问题会解决选择器/深/但不支持。

我有一个页面结构:

<div class="x">
    <div class="y"></div>
    <div>
        <div>
            <div>
                <span class="y"></span>
                <div>1</div>
                <label class="y"></label>
                <div>
                    <span class="y"></span>
                    <p>2</p>
                </div>
            </div>
        </div>
    </div>
    <div>
        <span class="y"></span>
        <div>3</div>
    </div>
    <div>
        <div>4</div>
        <div>
            <div>5</div>
        </div>
    </div>
    <div>6</div>
</div>

我需要一个选择器或xpath来选择:

<div>1</div>
<p>2</p>
<div>3</div>
<div>
    <div>4</div>
    <div>
        <div>5</div>
    </div>
</div>
<div>6</div>

我需要一个通用的解决方案。

2 个答案:

答案 0 :(得分:1)

这个XPath,

//div[@class="x"]//*[not(@class="y") and not(.//*[@class="y"])]

将选择没有div[@class="x"]属性的所有@class="y"个后代,并且没有任何具有@class="y"元素的后代,

<div>1</div>
<p>2</p>
<div>3</div>
<div>
        <div>4</div>
        <div>
            <div>5</div>
        </div>
    </div>
<div>4</div>
<div>
            <div>5</div>
        </div>
<div>5</div>
<div>6</div>

如果我们假设您的示例不完整,则与您的示例匹配。

答案 1 :(得分:1)

存在:has(...)伪类,但是出于性能原因,不能在样式表中使用它。所有浏览器的CSS引擎都受到了这一限制,因为每次它们呈现网页时,它们都会遍历整个DOM并应用与现有元素匹配的选择器(因此尚未查看其子级)。相反,此伪类通常用于专用选择器引擎,例如Sizzle(以其对jQuery的开发/使用而闻名)。

如果您想使用该伪类,则可以尝试:not(.y):not(:has(.y))。然后,为了获得最高结果,我仅选择不匹配元素的子元素(即:has(.y) > :not(:has(.y)))。一个警告是,如果类“ y”的元素有孩子。处理该问题的唯一方法是,对指定深度进行多次重复指定:not(.y)的伪类(我没有这样做)。这是一个实时示例:

// The selector
var elements = $('.x > :not(.y):not(:has(.y)), .x :has(.y) > :not(.y):not(:has(.y))');

// Format the HTML
var html = elements.map(function(){
    var dirty = this.outerHTML;

    // Get leading whitespace to remove
    var leading = (dirty.match(/\r?\n *(?= {4})/) || ['\r\n'])[0];
    // Create regex to replace whitespace
    var leading = new RegExp(leading.replace(/\r/,'\\r?').replace(/\n/,'\\n'), 'g');
    // Show newlines, whitespace in HTML
    var cleaned = $('<div>').text(dirty).html().replace(leading, '<br/>').replace(/ /g, '&nbsp;');

    return cleaned;
}).toArray();

// Add the HTML to the page
var results = $('#results');
for(var i=0; i<html.length; i++) {
    results.append($('<li>').html(html[i]));
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<!-- Sample HTML -->
<div class="x">
    <div class="y"></div>
    <div>
        <div>
            <div>
                <span class="y"></span>
                <div>1</div>
                <label class="y"></label>
                <div>
                    <span class="y"></span>
                    <p>2</p>
                </div>
            </div>
        </div>
    </div>
    <div>
        <span class="y"></span>
        <div>3</div>
    </div>
    <div>
        <div>4</div>
        <div>
            <div>5</div>
        </div>
    </div>
    <div>6</div>
</div>

<h3>Results</h3>
<ol id="results" class="y"></ol>