我使用Owin Self-hosting和WebApi编写了简单的服务器:
namespace OwinSelfHostingTest
{
using System.Threading;
using System.Web.Http;
using Microsoft.Owin.Hosting;
using Owin;
public class Startup
{
public void Configuration(IAppBuilder builder)
{
var config = new HttpConfiguration();
config.Routes.MapHttpRoute(
"Default",
"{controller}/{id}",
new { id = RouteParameter.Optional }
);
builder.UseWebApi(config);
}
}
public class Server
{
private ManualResetEvent resetEvent = new ManualResetEvent(false);
private Thread thread;
private const string ADDRESS = "http://localhost:9000/";
public void Start()
{
this.thread = new Thread(() =>
{
using (var host = WebApp.Start<Startup>(ADDRESS))
{
resetEvent.WaitOne(Timeout.Infinite, true);
}
});
thread.Start(); …Run Code Online (Sandbox Code Playgroud) 我正在用C#编写简单的屏幕抓取程序,为此我需要选择所有输入放在一个名为"aspnetForm"的表单中(页面上有2个表单,我不希望输入来自另一个),以及此表单中的所有输入都放在不同的表格,div中,或者只放在此表单的第一个子级别.
所以我写了非常简单的XPath查询:
//form[@id='aspnetForm']//input
Run Code Online (Sandbox Code Playgroud)
它在我测试的所有浏览器(Chrome,IE,Firefox)中按预期工作 - 它返回我想要的内容.
但是在HTMLAgilityPack中根本不起作用 - SelectNodes总是返回NULL.
我为测试编写的查询工作正常,但不返回我想要的.首先选择作为我的表单的第一个孩子的所有输入,然后选择返回的表单:
//form[@id='aspnetForm']/input
//form[@id='aspnetForm']
Run Code Online (Sandbox Code Playgroud)
是的,我知道我可以枚举上次查询的节点,或者在其结果上创建另一个SelectNodes,但我真的不想这样做.我想在浏览器中使用相同的查询.
XPath目前在HTMLAgilityPack中被破坏了吗?C#有任何替代的XPath实现吗?
更新:测试代码:
using HtmlAgilityPack;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace HtmlAGPTests
{
[TestClass]
public class XPathTests
{
private const string html =
"<form id=\"aspnetForm\">" +
"<input name=\"first\" value=\"first\" />" +
"<div>" +
"<input name=\"second\" value=\"second\" />" +
"</div>" +
"</form>";
private static HtmlNode GetHtmlDocumentNode()
{
var document = new HtmlDocument();
document.LoadHtml(html);
return document.DocumentNode;
}
[TestMethod]
public void TwoLevelXpathTest() // fail - nodes is NULL actually.
{
var query = …Run Code Online (Sandbox Code Playgroud) 我似乎在我的代码的这两个部分中误导或误用了代码.我理解是什么导致程序在调试时给我IsOperator错误消息.奇怪的是+运算符可以工作,但其他运算符都没有.
public bool IsValidData()
{
return
IsPresent(txtOperand1, "Operand 1") &&
IsDecimal(txtOperand1, "Operand 1") &&
IsWithinRange(txtOperand1, "Operand 1", 0, 1000000) &&
IsPresent(txtOperator, "Operator") &&
IsOperator(txtOperator, "+, -, *, /") &&
IsPresent(txtOperand2, "Operand 2") &&
IsDecimal(txtOperand2, "Operand 2") &&
IsWithinRange(txtOperand2, "Operand 2", 0, 1000000);
}
public bool IsOperator(TextBox textBox, string operators)
{
try
{
foreach (string s in operators.Split(new char[] { ',' }))
{
if (textBox.Text.Trim() == s)
return true;
else
throw new ArgumentException("The operator must be a valid operator: +,-, *, …Run Code Online (Sandbox Code Playgroud)