CSQuery是一个非常棒的C#库,可以帮助解析C#中的HTML。 https://github.com/jamietre/CsQuery
这是你对sizzler / jQuery所期待的所有善意,而且James Treworgy值得一些爱和钦佩。
为什么第二个选择第一个选择结果的结果是错误的元素数?
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);
答案 0 :(得分: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);