2016-04-05 10 views
2

Sorunun temel dayanağı, bir web hizmeti olabilecek veya olmayan bir veri listesi olan bir metin dosyanızın olmasıdır. Metin dosyasında bulunan web hizmetleri listesinden, her web hizmeti için mevcut olan web yöntemlerini ayrıştırmak ve bu verileri bir excel sayfasına yayınlamak istiyorum.Ayrıştırma çözümünü geliştirme

<Resource Name="APP1"> 
    <Uri UriType="PAGE" ResourceUri="http://exampleurl/default.aspx" /> 
</Resource> 
<Resource Name="App2"> 
    <Uri UriType="PAGE" ResourceUri="http://exampleurl2/example.aspx" /> 
</Resource> 
<Resource Name="App3"> 
    <Uri UriType="PAGE" ResourceUri="http://exampleurl3/exampleapp.asmx" /> 
</Resource> 

Temelde, son satırı Ben kullanmak istiyorum çizgidir:

Sana test veri neye benzediğini bir örnek vereyim. Bir kullanışlı hattın diğer örnek, Yani

<Resource Name="Example" WSDL="http://example.wsdl"> 
    <Uri UriType="ASMX" ResourceUri="http://example.asmx" /> 
</Resource> 

olduğunu ben aslında .asmx ve .wsdl dosyalar için arıyorum. Sorunu düşündüğüm yol, girişimi bu web hizmetlerinin her biri için yalnızca WSDL'leri aramak için standartlaştırmaktı. Bu yüzden .asmx URL'leri için ?wsdl ekleyeceğim.

Şimdi, bir çözümün altında uyguladım. Kaynak dosyada binlerce web hizmeti bulunduğundan ve potansiyel olarak web yöntemleri olduğundan, yürütme süresinin 1-2 saat kadar sürdüğünü görüyorum. Çalışma zamanını hızlandırmak için bu çözümün daha da geliştirilip geliştirilemeyeceğini merak ediyorum.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.IO; 
using System.Text.RegularExpressions; 
using System.Xml; 
using System.Net; 
using System.Data; 
using ClosedXML.Excel; 

namespace ParseWebservices 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 

      var lines = File.ReadAllText(@"PATH\SourceFIle.xml"); 
      int count = 0; 
      string text = ""; 
      DataTable Webservices= new DataTable(); 
      Webservices.Columns.Add("Wsdl URL"); 
      Webservices.Columns.Add("Webservice Name"); 
      Webservices.Columns.Add("WebMethod"); 

      Regex r = new Regex("(?<=ResourceUri=\")(.*)(.asmx)(?=\")", RegexOptions.IgnoreCase); 
      Match m = r.Match(lines.ToString()); 
      while (m.Success) 
      { 


       try 
       { 

        string[] test = m.ToString().Split('/'); 
        string webservicename = test[test.Length - 1].Replace(".asmx", ""); 
        string wsdlurl=""; 

        var webClient = new WebClient(); 
        string readHtml=""; 
        try 
        { 
         readHtml = webClient.DownloadString(wsdlurl); 
        } 
        catch (Exception excxx) 
        { 
         wsdlurl = m.ToString().Replace(".asmx", ".wsdl"); 
         readHtml = webClient.DownloadString(wsdlurl); 
        } 

        int count2 = 0; 
        string text2 = ""; 
        Regex r2 = new Regex(@"(?<=s:element name\=\"")(.*)(?=Response"")", RegexOptions.IgnoreCase); 
        Match m2 = r2.Match(readHtml); 
        while (m2.Success) 
        { 
         DataRow dr = Webservices.NewRow(); 

         dr[0] = wsdlurl; 
         dr[1] = webservicename; 
         dr[2] = m2.ToString(); 
         Console.WriteLine(wsdlurl + "\n" + webservicename + "\n" + m2.ToString()); 
         Webservices.Rows.Add(dr); 
         count2++; 
         m2 = m2.NextMatch(); 
        } 
        count++; 
        m = m.NextMatch(); 
       } 
       catch (Exception ex) 
       { 
        m = m.NextMatch(); 
       } 
      } 

      XLWorkbook wb = new XLWorkbook(); 
      wb.Worksheets.Add(Webservices, "Example"); 
      wb.SaveAs(@"PATH\example.xlsx"); 
     } 
    } 
} 

Bu çözüm hakkında beğenmediğim bir şey, özel durumlara dayanmasıdır. Regex, .asmx dizeleri ile eşleştiğinden, .wsdl dizeleri bulmakta başarısız olacağını anladım. Ama aynı zamanda, bir .wsdl içeren kaynak metinde, .asmx öneki tam olarak aynı olduğunu fark ettim. Bu yüzden bu test senaryoları için hata işlemeyi ekledim, ama kesinlikle ideal değil.

Her neyse, nasıl daha iyi hale getirileceğini ve daha hızlı hale getirilebileceğini (ve daha iyi bir şekilde) öneriyorum.

+0

Bu belge tamamen geçerli bir XML gibi görünüyor, verileri ayrıştırmak için XDocument veya XmlDocument kullanmayı denediniz mi? Çok büyük bir dosyayı ayrıştırmak için bir regex kullanmaktan çok daha hızlı olacaktır. – Gusman

+0

Burada yanlış bir yaklaşım olabilir. Giriş dosyalarınız XML'de ise, XML ayrıştırma ve regex'e bakmalısınız. –

+0

Ayrıca, tüm url'leri başka bir iş parçacığında seri olarak denetlemek yerine bu url'leri tüketen bir sıra oluşturmak ve bu testleri pararlell – Gusman

cevap

0

Önerileriniz gibi, örneğin geçerli bir XML ise, bir XML ayrıştırma çözümünün Regex ile çalışmaktan daha hızlı olabileceğinden şüpheleniyorum. döndürür

var files = XElement.Parse(xmlString) 
    .Descendants("Resource").SelectMany(resource => 
    { 
     XAttribute wsdlAttribute = resource.Attribute("WSDL"); 
     XAttribute resourceUriAttribute = resource.Element("Uri").Attribute("ResourceUri"); 
     if (wsdlAttribute != null) 
      return new[] { wsdlAttribute.Value, resourceUriAttribute.Value }; 
     else 
      return new[] { resourceUriAttribute.Value }; 
    }).Select(uri => Path.GetFileName(uri)); 

:

  • default.aspx
  • example.aspx
  • exampleapp.asmx
  • Example.wsdl
  • example.asmx
  • Sen gibi bir şey deneyebilirsiniz

Ben Yayınınızdan oluşturulan test xml dizesi kullanarak:

 string xmlString = 
@"<Root> 
    <Resource Name=""APP1""> 
     <Uri UriType=""PAGE"" ResourceUri=""http://exampleurl/default.aspx"" /> 
    </Resource> 
    <Resource Name=""App2""> 
     <Uri UriType=""PAGE"" ResourceUri=""http://exampleurl2/example.aspx"" /> 
    </Resource> 
    <Resource Name=""App3""> 
     <Uri UriType=""PAGE"" ResourceUri=""http://exampleurl3/exampleapp.asmx"" /> 
    </Resource> 
    <Resource Name=""Example"" WSDL=""http://example.wsdl""> 
     <Uri UriType=""ASMX"" ResourceUri=""http://example.asmx"" /> 
    </Resource> 
</Root>"; 

Ben senin çözümü daha hızlı olacağı söz veremem, ama bunu test edilir daha vardır! İşlenecek birden çok dosyanız varsa bunu da işleyebilirsiniz.

+0

Bunu bir şans vereceğim ve sonuçlarla birlikte rapor vereceğim! – user2044754

1

Bu yavaş, çünkü hepsi tek bir iş parçacığında yapıldı!(Xml veya regex'in yavaşlık ile çok az bir ilgisi olup olmayacağı: gerçekten sizi yavaşlatan inline web istekleridir)

Kaynak dosyanız olmadan çalışma örneği yapmak zordur. Eşzamanlı olmayan Url'lerin listesini yüklemek için bir yardımcı uzantısı - açıkçası kodunuzu etrafı doldurmanız gerekir.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.IO; 
using System.Text.RegularExpressions; 
using System.Xml; 
using System.Net; 
using System.Data; 
using System.Collections.Concurrent; 

using System.Threading.Tasks; 

namespace ParseWebservices 
{ 
    static class UrlLoaderExtension 
    { 
    public static async Task<ConcurrentDictionary<string, string>> LoadUrls(this IEnumerable<string> urls) 
    { 
     var result = new ConcurrentDictionary<string,string>();     
     Task[] tasks = urls.Select(url => { 
      return Task.Run(async() => 
      { 
       using (WebClient wc = new WebClient()) 
       { 
        // Console.WriteLine("Thread: " + System.Threading.Thread.CurrentThread.ManagedThreadId); 
        try 
        { 
         var r = await wc.DownloadStringTaskAsync(url); 
         result[url] = r; 
        } 
        catch (Exception err) 
        { 
         result[url] = err.Message; 
        } 
       } 
      }); 
     }).ToArray();     
     await Task.WhenAll(tasks); 
     return result; 
    } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      var requests = new ConcurrentDictionary<string,string>(); 

      // load desired urls into the structure 
      requests["http://www.microsoft.com"] = null; 
      requests["http://www.google.com"] = null; 
      requests["http://www.google.com/asdfdsaf"] = null; 

      try 
      { 
       Task.Run(async() => 
       { 
        requests = await requests.Keys.LoadUrls(); 
       }).GetAwaiter().GetResult(); 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine("Error: " + ex.Message); 
       Console.ReadLine(); 
       return; 
      } 

      Console.WriteLine("Finished loading data concurrently"); 
      Console.ReadLine(); 

      // this part is synchronous (it's not waiting for IO) 
      foreach(var url in requests.Keys) 
      { 
       var response = requests[url]; 
       Console.WriteLine(response); // 
       Console.WriteLine("Response from " + url); 
       Console.ReadLine(); 
      } 



      Console.Write("DONE"); 
      Console.ReadLine(); 
     } 
    } 
} 

Ben size verileri yüklemek mümkün olacak ne kadar hızlı bir fikir edinmek için bu demo içine URL'ler koymak öneririz: tüm yanıtları sahip olduğunda anlatır nokta bitmiş yükleniyor oluyor toplanmış. Eğer (çok!) çok daha hızlı şudur, o zaman da başka mantık doldurmak için motive olacak nasıl tespit ettik sonra

Sonra etrafta o :)

yardımcı olur Umut!

+0

@ user2044754 Bunu denemediniz mi? :) – Nathan