2010-02-24 54 views
5

我需要允许高级用户输入XPath表达式,并向他们显示找到的值或节点或属性。在.Net框架中,可以使用System.Xml.XPath.Extensions来调用XPathEvaluate,但Silverlight没有这个MSDN reference。是否有人重写了在Silverlight中使用的扩展方法?最好的方法是什么?为什么不在Silverlight或工具包中提供(vote on the issue here)?如何评估Silverlight中的XPath表达式?

+0

+1我同意我希望看到自己的扩展方法的端口。 – AnthonyWJones 2010-02-24 19:21:40

+0

“高级用户”不是开发者吗?需要支持多大范围的XPath? – AnthonyWJones 2010-02-25 09:03:23

+0

“高级用户”,如某人想要如何使用Xpath而不是我创建的用于帮助他们完成此操作的其余UI。所以他们只需要输入xPath,我会向他们展示结果。 – Aligned 2010-02-25 20:11:09

回答

0

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

第一:

Web项目创建一个通用的处理程序。添加下面的代码的ASHX文件为您的ProcessRequest(简化为简洁):

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); 

    } 

应当注意的是,有一些命名空间,你需要的XML处理引用:

  1. System.IO

  2. 的System.Xml

  3. System.Xml.XPat^h

  4. System.Xml.Linq的

二:

你需要一些代码,将让你做出一个异步邮寄到通用处理器。下面的代码是漫长的,但本质上你通过以下事项:

  1. 您的通用处理器

  2. 键值对(假设XML文档中的XPath)

  3. 的字典的URI

    成功和失败的回调

  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); 
    } 
} 

三:

请来电转接到您的实用程序类,并通过您的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); 

    } 

让我重申,这里的代码是为简洁起见简化。您可能希望使用序列化程序将更复杂的类型传递给通用处理函数。当您从context.Request.Form集合中获取值时,您需要以防御性方式编写空值守卫“完整性检查”。但基本想法如上所述。

+0

-1。这些天我很少冷静下来,但在这种情况下,我感到有必要这样做。将XML编码为'x-www-form-urlencoded'(带有可能会产生的各种字符编码令人头痛的问题),然后将其全部恢复到服务器上,以执行XPath并返回结果(这也可能很大),据我所知,也会产生难以理解的结果。 – AnthonyWJones 2010-02-25 08:16:36

+0

安东尼,我把你的罕见downvote作为一个“好点”,但我鼓励你提供一个解决方案。 xml文件可能非常大(例如iTunes库),但在许多情况下,它们的设计较小(例如,典型的RSS提要)。带有字符编码的AJAX样式文章(Server.UrlDecode可能应该在示例中)工作正常(取上面的代码并实现它,你将能够看到自己)。 – t3rse 2010-02-25 14:53:00

1

我认为XPath在Silverlight中不可用的原因是MS希望您使用Linq来代替XML。但这并不完全有助于你。不幸的是,我认为这将很难实现你想要的。如果您必须具备此功能,我认为您将不得不求助于将查询发送到服务器,在那里对其进行评估并返回结果。这是丑陋的,但我认为这是唯一的方法。

+0

我非常怀疑微软__want__你使用Linq。考虑到希望将下载量降到最低,并且Linq非常擅长用XPath处理它未优先处理的事实,它更有可能。 – AnthonyWJones 2010-02-24 19:21:09

+2

事实证明,XPath支持在Silverlight 4中可用: http://programmerpayback.com/2010/04/01/xpath-support-in-silverlight-4-xpathpad/ – 2010-04-06 08:35:49