0

CSQuery 是一个很棒的 C# 库,有助于在 C# 中解析 HTML。 https://github.com/jamietre/CsQuery

这是您对 sizzler/jQuery 的所有期望,而 James Treworgy 值得一些爱和钦佩。

为什么第一个 Select 的结果中的第二个 Select 会导致错误数量的元素?

CQ fragment = CQ.CreateFragment(@"
<div>
    <ul>
        <li class=""number english"">one</li>
        <li class=""number english"">two</li>
        <li class=""number english"">three</li>
        <li class=""number english"">four</li>
        <li class=""number english"">five</li>
    </ul>
    <ul>
        <li class=""number spanish"">uno</li>
        <li class=""number spanish"">dos</li>
        <li class=""number spanish"">tres</li>
        <li class=""number spanish"">quatro</li>
        <li class=""number spanish"">cinco</li>
    </ul>
</div>
");

Assert.AreEqual(2, fragment["ul"].Length);
CQ english = fragment["ul:first"];
CQ spanish = fragment["ul:last"];
Assert.AreEqual(1, english.Length);
Assert.AreEqual(1, spanish.Length);

// english seems to not represent only the first ul, but the entire DOM
CQ englishNumbers = english["li.number"]; 
Assert.AreEqual(5, englishNumbers.Length); // Failed, expected <5> and was <10>

// Both of these methods work. I'm at a loss for as to why the first does not.
CQ spanishNumbers = spanish["li.number", spanish[0]]; // Give it context of where to start searching from
Assert.AreEqual(5, spanishNumbers.Length);

CQ spanishNumbers2 = spanish.Select("li.number", spanish.Elements);
Assert.AreEqual(5, spanishNumbers2.Length);
4

1 回答 1

1

我一直在阅读源代码并编写更多测试,并认为我已经弄清楚了。

CsQuery/CQ_jQuery/ Select.cs 与public CQ Select(string selector, IDomObject context). public CQ Select(string selector)这一切都归结为public CQ Select(Selector selector)这个诗意的评论。

// When running a true "Select" (which runs against the DOM, 
// versus methods that operate against the selection set) 
// we should use the CsQueryParent document, which is the DOM
// that sourced this.

我想要的魔法是在使用这种方法时public Selector ToFilterSelector()CsQuery/Engine/Selector.cs

// Selecting from a resolved Select is the same as selecting from the root dom
CQ entireDomNumbers = fragment["li.number"];
CQ englishNumbers = english["li.number"];
Assert.AreEqual(entireDomNumbers.Length, englishNumbers.Length);

// When you want to select from a sub-part of the dom, explicitly use it as context
IEnumerable<IDomObject> spanishDomObjects = spanish;
CQ spanishNumbers = spanish["li.number", spanishDomObjects];
Assert.AreEqual(5, spanishNumbers.Length);

// Or from some specific part of the resolved CQ, again explicitly
IDomObject spanishDomObject = spanish[0];
CQ spanishNumbers2 = spanish["li.number", spanishDomObject];
Assert.AreEqual(5, spanishNumbers2.Length);

// Indexer [string, context] is same as Select(string, context) method
CQ spanishNumbers3 = spanish.Select("li.number", spanishDomObject);
Assert.AreEqual(5, spanishNumbers3.Length);

// Or in reverse from an IDomObject just for fun
CQ spanishNumbers3b = spanishDomObject.Cq().Select("li.number", spanish);
Assert.AreEqual(5, spanishNumbers3b.Length);

// Or from the collection...
CQ spanishNumbers4 = spanish.Select("li.number", spanishDomObjects);
Assert.AreEqual(5, spanishNumbers4.Length);

// in the end, Find was the droid I was looking for
CQ findSpanishNumbers = spanish.Find("li.number");
Assert.AreEqual(5, findSpanishNumbers.Length);
于 2014-05-09T04:56:37.413 回答