jquery selectors: an uncommon use case

2019-09-04 04:43发布

问题:

I have to parse an html page organized this way:

<li id="list">
  <a id="cities">Cities</a>
  <ul>
    <li>
      <a class="region" title="liguria">Liguria</a>
      <ul>
        <li>
          <a class="genova">Genova</a>
        </li>
        <li>
          <a class="savona">Savona</a>
        </li>
      </ul>
    </li>
    <li>
      <a class="region" title="lazio">Lazio</a>
      <ul>
        <li>
          <a class="roma">Roma</a>
        </li>
      </ul>
    </li>
  </ul>
</li>

I need to extract a list of all the cities. I don't care about regions... I am using cheerio from node.js, but I added jquery to the tags since cheerio uses jquery-style selector (AFAIK...).

I have come with this partial solution, partially working (it only lists first region group cities...):

$('li[id="list"] li li').each(function(i, elem) {
  console.log('city:', elem.children[0].next.children[0].data);
});

As you can see, I'm quite confused... :-(
Any clue?

回答1:

Try: $('li#list ul li ul li a').each(function() { console.error("City: "+$(this).html()); });

As noted below, the selector could be simply $('li#list li li a').



回答2:

Try this

$('li[id="list"] ul li').each(function(i, elem) {
     ...work on each li containing the region ...
});


回答3:

Note that when using an id selector, since by definition an id is unique, the selector does not need any other qualifiers such as the tag name. And usually you would only use tagname[id...] if you're matching a substring in the ID: ^ - at the beginning, $ - at the end or * - anywhere.

Another approach would be to use :not() to exclude the a elements that should be left out:

$('#list a:not(.region,#cities)').each(function(i, a) {
    console.log( i, a.innerHTML );
}); 

You have several options for valid selectors you can use:

  • #list ul ul a
  • #list li li a
  • #list ul ul li a

$('#list a:not(.region,#cities)').each(function(i, a) {
    console.log( i, a.innerHTML );
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<li id="list">
  <a id="cities">Cities</a>
  <ul>
    <li>
      <a class="region" title="liguria">Liguria</a>
      <ul>
        <li>
          <a class="genova">Genova</a>
        </li>
        <li>
          <a class="savona">Savona</a>
        </li>
      </ul>
    </li>
    <li>
      <a class="region" title="lazio">Lazio</a>
      <ul>
        <li>
          <a class="roma">Roma</a>
        </li>
      </ul>
    </li>
  </ul>
</li>

AND to get all the cities in an array called cities you can use the jQuery .map() method:

var cities = $('#list li li a').map(function() {
    return this.innerHTML;
}).get();

var cities = $('#list li li a').map(function() {
    return this.innerHTML;
}).get();
console.log( cities );
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<li id="list">
  <a id="cities">Cities</a>
  <ul>
    <li>
      <a class="region" title="liguria">Liguria</a>
      <ul>
        <li>
          <a class="genova">Genova</a>
        </li>
        <li>
          <a class="savona">Savona</a>
        </li>
      </ul>
    </li>
    <li>
      <a class="region" title="lazio">Lazio</a>
      <ul>
        <li>
          <a class="roma">Roma</a>
        </li>
      </ul>
    </li>
  </ul>
</li>