Как я могу оценить выражение XPath в Silverlight? - PullRequest
5 голосов
/ 24 февраля 2010

Мне нужно разрешить опытному пользователю вводить выражение XPath и показывать им найденные значения или узлы или атрибуты. В .Net Framework System.Xml.XPath.Extensions можно использовать для вызова XPathEvaluate, но Silverlight не имеет этой ссылки MSDN . Кто-нибудь переписывал методы расширения для использования в Silverlight? Каков наилучший подход? Почему они не доступны в Silverlight или в наборе инструментов ( голосуйте по этому вопросу здесь )?

Ответы [ 3 ]

1 голос
/ 24 февраля 2010

Я думаю, что причина отсутствия XPath в Silverlight заключается в том, что MS хочет, чтобы вы вместо этого использовали Linq to XML. Но это не совсем вам помогает. К сожалению, я думаю, что будет трудно достичь того, что вы хотите. Если вам нужна эта функциональность, думаю, вам придется прибегнуть к отправке запроса на сервер, его оценке и возвращению результата. Это некрасиво, но я думаю, что это единственный выход.

0 голосов
/ 10 сентября 2014

Теперь кажется, что пакет NuGet , который обеспечивает эту функциональность. Автор указан как Microsoft.

0 голосов
/ 24 февраля 2010

Одним из решений является использование универсального обработчика и передача обработки на сервер по асинхронному запросу. Вот шаг за шагом:

Первый:

Создайте универсальный обработчик в вашем веб-проекте . Добавьте файл 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.XPath

  4. System.Xml.Linq

Второй:

Вам нужен код, который позволил бы вам сделать асинхронную запись в общий обработчик. Код ниже является длинным, но по существу вы передаете следующее:

  1. Uri вашего универсального обработчика

  2. Словарь пар ключ-значение (при условии, что документ xml и xpath)

  3. Обратные вызовы для успеха и неудачи

  4. Ссылка на таймер отправки UserControl, чтобы вы могли получить доступ к своему пользовательскому интерфейсу (при необходимости) в обратных вызовах.

Вот код, который я поместил в служебный класс:

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. Но основная идея описана выше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...