jquery选择器逻辑AND?

时间:2010-05-26 20:00:25

标签: jquery xml jquery-selectors xml-parsing

在jQuery中,我试图只选择安装节点,其中a和b的文本值为64,并相应地“测试”。如果没有64并且“测试”存在,我也想回退到32。我在下面的代码中看到的是,返回的是32位而不是64位。

XML:


<thingses>
    <thing>
        <a>32</a> <-- note, a here is 32 and not 64 -->
        <other>...</other>
        <mount>sample 1</mount>
        <b>test</b>
    </thing>
    <thing>
        <a>64</a>
        <other>...</other>
        <mount>sample 2</mount>
        <b>test</b>
    </thing>
    <thing>
        <a>64</a>
        <other>...</other>
        <mount>sample 3</mount>
        <b>unrelated</b>
    </thing>
    <thing>
        <a>128</a>
        <other>...</other>
        <mount>sample 4</mount>
        <b>unrelated</b>
    </thing>
</thingses>

不幸的是,我无法控制XML,因为它来自其他地方。

我现在正在做的是:


var ret_val = '';

$data.find('thingses thing').each(function(i, node) {
    var $node = $(node), found_node = $node.find('b:first:is(test), a:first:is(64)').end().find('mount:first').text();
    if(found_node) {
        ret_val = found_node;
        return;
    }

    found_node = $node.find('b:first:is(test), a:first:is(32)').end().find('mount:first').text();
    if(found_node) {
        ret_val = found_node;
        return;
    }

    ret_val = 'not found';
});

// expected result is "sample 2", but if sample 2's parent "thing" was missing, the result would be "sample 1"
alert(ret_val);

对于我正在使用的“:is”选择器:


    if(jQuery){
        jQuery.expr[":"].is = function(obj, index, meta, stack){
            return (obj.textContent || obj.innerText || $(obj).text() || "").toLowerCase() == meta[3].toLowerCase();
        };
    }

必须有一种比我做得更好的方式。我希望我可以用“AND”或其他东西替换“,”。 :)

非常感谢任何帮助。谢谢!

3 个答案:

答案 0 :(得分:0)

为什么在end()之后致电find()?我可能无法正确理解您的意图,但end()会将您带回$node,以便后续的find("mount:first")只返回您的第一个mount孩子。

我错了吗?

修改

此外,你为什么要对所有.each进行thing?这样,您的ret_value实际上会获得符合 64-if-not-then-32的 last mount的{​​{1}}值条件。

如果你想选择第一个 64 / test thing,如果没有这样的东西,那么第一个 32 / test ,那为什么不要你明确地写这个吗?

thing

您可以封装那个长查询以使代码更具可读性:

var ret_value = $data.find( "thingses > thing:has( a:is(64) ):has( b:is(test) ) > mount" ).text();
if ( !ret_value )
    ret_value = $data.find( "thingses > thing:has( a:is(32) ):has( b:is(test) ) > mount" ).text();

我是否误解了你的需求?因为我有点困惑: - )

答案 1 :(得分:0)

这似乎对我有用:

var el = $('thingses thing')
    .has('b:contains("test")')
    .has('a:contains(64)');
if(!el.length) 
    el = $('thingses thing')
        .has('b:contains("test")')
        .has('a:contains(32)');
alert(el.find('mount:first').text());

答案 2 :(得分:0)

各种想法:

  • 使用兄弟选择器(Hierarchy selectors in jQuery
    b可以在a之前或之后,否则您可以保留选择器的一半

    find('b:first:is(test)~a:first:is(64),a:first:is(64)~b:first:is(test)')

  • 找一个,然后回去找另一个。我想这可能是丑陋的

    查找( 'B:第一:是(试验))母体()找到。(' 一个:第一:是(64)')

  • custom jQuery selectors可以使用参数,因此您可以编写:allAtOnce选择器:)