如何在Silverlight中评估XPath表达式?

Ali*_*ned 5 xml silverlight xpath

我需要允许高级用户输入XPath表达式并向他们显示找到的值或节点或属性.在.Net框架中,System.Xml.XPath.Extensions可用于调用XPathEvaluate,但Silverlight没有此MSDN引用.有没有人重写过在Silverlight中使用的扩展方法?最好的方法是什么?为什么它们不能在Silverlight或工具包中使用(在此处对此问题进行投票)?

t3r*_*rse 0

一种解决方案是使用通用处理程序并将异步请求的处理外包给服务器。这是一步一步:

第一的:

在您的Web 项目中创建通用处理程序。为您的 ProcessRequest 添加包含以下代码的 ASHX 文件(为简洁起见,进行了简化):

    public void ProcessRequest(HttpContext context)
    {
        context.Response.ContentType = "text/plain";

        string xml = context.Request.Form["xml"].ToString();
        string xpath = context.Request.Form["xpath"].ToString();

        XmlReader reader = new XmlTextReader(new StringReader(xml));
        XDocument doc = XDocument.Load(reader);

        var rawResult = doc.XPathEvaluate(xpath);
        string result = String.Empty;
        foreach (var r in ((IEnumerable<object>)rawResult)) 
        {
            result += r.ToString();
        }

        context.Response.Write(result);

    }
Run Code Online (Sandbox Code Playgroud)

应该注意的是,您需要引用一些命名空间来进行 xml 处理:

  1. 系统IO

  2. 系统.Xml

  3. 系统.Xml.XPath

  4. 系统.Xml.Linq

第二:

您需要一些代码来允许您向通用处理程序进行异步发布。下面的代码很长,但基本上您传递了以下内容:

  1. 通用处理程序的 Uri

  2. 键值对的字典(假设xml文档和xpath)

  3. 成功和失败的回调

  4. 对 UserControl 的调度计时器的引用,以便您可以在回调中访问您的 UI(如果需要)。

这是我放置在实用程序类中的一些代码:

public class WebPostHelper
{
    public static void GetPostData(Uri targetURI, Dictionary<string, string> dataDictionary, Action<string> onSuccess, Action<string> onError, Dispatcher threadDispatcher)
    {
        var postData = String.Join("&",
                        dataDictionary.Keys.Select(k => k + "=" + dataDictionary[k]).ToArray());

        WebRequest requ = HttpWebRequest.Create(targetURI);
        requ.Method = "POST";
        requ.ContentType = "application/x-www-form-urlencoded";
        var res = requ.BeginGetRequestStream(new AsyncCallback(
            (ar) =>
            {
                Stream stream = requ.EndGetRequestStream(ar);
                StreamWriter writer = new StreamWriter(stream);
                writer.Write(postData);
                writer.Close();
                requ.BeginGetResponse(new AsyncCallback(
                        (ar2) =>
                        {
                            try
                            {
                                WebResponse respStream = requ.EndGetResponse(ar2);
                                Stream stream2 = respStream.GetResponseStream();
                                StreamReader reader2 = new StreamReader(stream2);
                                string responseString = reader2.ReadToEnd();
                                int spacerIndex = responseString.IndexOf('|') - 1;
                                string status = responseString.Substring(0, spacerIndex);
                                string result = responseString.Substring(spacerIndex + 3);
                                if (status == "success")
                                {
                                    if (onSuccess != null)
                                    {
                                        threadDispatcher.BeginInvoke(() =>
                                        {
                                            onSuccess(result);
                                        });
                                    }
                                }
                                else
                                {
                                    if (onError != null)
                                    {
                                        threadDispatcher.BeginInvoke(() =>
                                        {
                                            onError(result);
                                        });
                                    }
                                }
                            }
                            catch (Exception ex)
                            {
                                string data2 = ex.ToString();
                            }
                        }
                    ), null);

            }), null);
    }
}
Run Code Online (Sandbox Code Playgroud)

第三:

调用您的实用程序类并传递 xml 和 xpath:

    private void testButton_Click(object sender, RoutedEventArgs e)
    {
        Dictionary<string, string> values = new Dictionary<string, string>();
        values.Add("xml", "<Foo />");
        values.Add("xpath", "/*");

        //Uri uri = new Uri("http://eggs/spam.ashx");
        Uri uri = new Uri("http://localhost:3230/xPathHandler.ashx");

        WebPostHelper.GetPostData(uri, values,
            (result) =>
            {
                MessageBox.Show("Your result " + result);
            },
            (errMessage) =>
            {
                MessageBox.Show("An error " + errMessage);
            },
            this.Dispatcher);

    }
Run Code Online (Sandbox Code Playgroud)

让我重申一下,为了简洁起见,这里的代码已被简化。您可能希望使用序列化程序将更复杂的类型传递给通用处理程序或从通用处理程序传递出更复杂的类型。当您从 context.Request.Form 集合中获取值时,您需要以防御方式编写空保护“健全性检查”。但基本思想如上所述。