2016-04-01 8 views
0

Ich versuche, einige XML-Dateien (mit LINQ) zu analysieren, um diese Daten in der DB zu speichern. Im Folgenden ist das Format für einen der Dienst, und es gibt Dutzende von ihnen mehr, jeder mit verschiedenen Knotenmustern und Struktur.LINQ2XML Ansatz, um Iteration durch XML zu verallgemeinern

Gibt es eine Möglichkeit, diesen Ansatz zu verallgemeinern, so dass ich alle diese Dienste durch eine einzige Methode/Codezeilen iterieren kann? ohne daran zu stören, wie die childNodes angeordnet sind?

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<deviceState> 
<id>203948-2908093-203984902-29348020-290lk</id> 
<device>Mirron</device> 
<variable> 
     <id>Plug - Meter.VI</id> 
     <text> 
     <textValue> 
      <value>0.000000</value> 
     </textValue> 
     </text> 
    </variable> 

<variable> 
     <id>AEB</id> 
     <text> 
     <textStr>-</textStr> 
     </text> 
    </variable> 
<variable> 
     <id>DESCRIPTION</id> 
     <text> 
     <textStr /> 
     </text> 
    </variable> 
<variable> 
     <id>VDTTM</id> 
     <text> 
     <textDate> 
      <date>01042016103658</date> 
     </textDate> 
     </text> 
    </variable> 
<variable> 
     <id>STATUS</id> 
     <text> 
     <textValue> 
      <value>1.000000</value> 
     </textValue> 
     </text> 
    </variable> 
</deviceState> 

Ich möchte eine Funktionalität erreichen, wo ich Werte jeder Variable-ID durch die Angabe eines Suchfilter zugreifen zugreifen können und dann Wert, es ist direkt, ohne durch folgende sinnlosen Tags gestört zu werden.

<text><textValue> or <text><textDate> or <text><textStr/> or <text> 
<textvalue><value> 

so etwas wie, lässt new devices {a.id=node("id"), a.value=node("valu")} sagen.

Derzeit verwende ich folgenden Code, der den Trick tut, aber es ist nicht effizient, weder in der Geschwindigkeit noch in der Verwaltbarkeit.

XDocument x = XDocument.Parse(_back); 
      string back = ""; 
       string xvalue, yvalue; 
       foreach (XElement xe in x.Descendants().Take(1)) 
       { 

        var s = xe.Value.IndexOf("Plug - Meter.VI"); 
        var val = xe.Value.Substring(s, 25); 
        back= val.Substring(val.LastIndexOf("I")+1, 10); 
       break; 
       } 

Jede mögliche Führung sehr geschätzt werden. Danke


Basierend auf Monty's Feedback, das ist was ich benutze.

public protoDCM_CornerL08UMS_View() 
     { 
      InitializeComponent(); 
      synchronizationContext = SynchronizationContext.Current; 

      StartingMeter(); 

     } 


    private async void StartingMeter() 
     { 
      string val="0"; 
      max = min = 0; 

      await Task.Run(() => 
      { 
       do 
       { 
        UpdateUI(val,max,min); 
        val = fetchData(); 
        Double temp =0; 
        if (Double.TryParse(val,out temp)) 
        { 
         if(min==0&&max==0) 
         { 
          min = max = temp; 
         } 
         if(temp>max) 
         { 
          max = temp; 
         } 
         if(temp<min) 
         { 
          min = temp; 
         } 

        } 
        val = temp.ToString(); 
       } 
       while (true); 

      }); 
     } 

    private void UpdateUI(string value, Double _max , Double _min) 
     { 
      var timeNow = DateTime.Now; 

      if ((DateTime.Now - previousTime).Milliseconds <= 50) return; 

      synchronizationContext.Post(new SendOrPostCallback(o => 
      { 
       lblInstant.Text= (string)o; 
      }), value); 

      synchronizationContext.Post(new SendOrPostCallback(o => 
      { 
       lblMax.Text = (string)o; 
      }), _max.ToString()); 



      synchronizationContext.Post(new SendOrPostCallback(o => 
      { 
       lblMin.Text = (string)o; 
      }), _min.ToString()); 

      previousTime = timeNow; 
     } 

    public Stream GenerateStreamFromString(string s) 
       { 
        MemoryStream stream = new MemoryStream(); 
        StreamWriter writer = new StreamWriter(stream); 
        writer.Write(s); 
        writer.Flush(); 
        stream.Position = 0; 
        return stream; 
       } 

     private string fetchData() 
     { 


       String _back = HttpGet("http://xxx.xxx.xxx"+Global.Node.Current.Device.Address+"/services/devices/deviceState.xml?id=D83AE139-E0C9-4B15-B2A9-6E0B57B28ED1?type=ALL"); 
      //_back = FormatXML(Response); 
      try 
      { 
       DeviceState deserializedXML = new DeviceState(); 

       XmlSerializer serializer = new XmlSerializer(typeof(DeviceState)); 
       using (Stream stream = GenerateStreamFromString(_back)) 
       { 
        deserializedXML = (DeviceState)serializer.Deserialize(stream); 

        var x = (from z in deserializedXML.Variable 
           where z.Id == "Plug - Meter.VI" 
           select new 
           { 
            Id = z.Id, 
           value= (z.Text.TextDate == null? 
           (z.Text.TextStr == null 
           ? (z.Text.TextValue == null 
           ? "No Text Value!" : z.Text.TextValue.Value.ToString()) : z.Text.TextStr.ToString()) : z.Text.TextDate.Date.ToString()) }).FirstOrDefault(); 

        return x.value; 

       } 
      } 
      catch (Exception w) 
      { 
       MessageBox.Show(w.ToString()); 
       return "0.0"; 
      } 
     } 

    public static string HttpGet(string URI) 
     { 
      try 
      { 

       System.Net.WebRequest req = System.Net.WebRequest.Create(URI); 
       req.Method = "GET"; 
       System.Net.WebResponse resp = req.GetResponse(); 
       System.IO.StreamReader sr = new System.IO.StreamReader(resp.GetResponseStream()); 
       return sr.ReadToEnd().Trim(); 
      } 
      catch (Exception sl) 
      { 
return sl.ToString(); 
      } 
     } 
+0

Welche Datenbank verwenden Sie? Möglicherweise möchten Sie die XML-Datei direkt in die Datenbank laden, anstatt sie in C# zu analysieren. – jdweng

+0

Ich benutze MS SQLSERVER, aber bevor ich das mache, muss ich diese Informationen verarbeiten. – Shahzad

+0

Wie groß ist das XML? Für große XML mit XmlTextReader ist besser. Sie müssen nicht die gesamte Datei auf einmal lesen. Gibt es einen Grund, warum Sie die Methode Parse() anstelle von Load() verwenden? – jdweng

Antwort

1

Try this ....

Usings

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Linq; 
using System.Xml.Serialization; 

Klassen

[XmlRoot(ElementName = "textValue")] 
public class TextValue 
{ 
    [XmlElement(ElementName = "value")] 
    public string Value { get; set; } 
} 

[XmlRoot(ElementName = "text")] 
public class Text 
{ 
    [XmlElement(ElementName = "textValue")] 
    public TextValue TextValue { get; set; } 
    [XmlElement(ElementName = "textStr")] 
    public string TextStr { get; set; } 
    [XmlElement(ElementName = "textDate")] 
    public TextDate TextDate { get; set; } 
} 

[XmlRoot(ElementName = "variable")] 
public class Variable 
{ 
    [XmlElement(ElementName = "id")] 
    public string Id { get; set; } 
    [XmlElement(ElementName = "text")] 
    public Text Text { get; set; } 
} 

[XmlRoot(ElementName = "textDate")] 
public class TextDate 
{ 
    [XmlElement(ElementName = "date")] 
    public string Date { get; set; } 
} 

[XmlRoot(ElementName = "deviceState")] 
public class DeviceState 
{ 
    [XmlElement(ElementName = "id")] 
    public string Id { get; set; } 
    [XmlElement(ElementName = "device")] 
    public string Device { get; set; } 
    [XmlElement(ElementName = "variable")] 
    public List<Variable> Variable { get; set; } 
} 

Code

 try 
     { 
      DeviceState deserializedXML = new DeviceState(); 
      // Deserialize to object 
      XmlSerializer serializer = new XmlSerializer(typeof(DeviceState)); 
      using (FileStream stream = File.OpenRead(@"xml.xml")) 
      { 
       deserializedXML = (DeviceState)serializer.Deserialize(stream); 

       // Now get all your IDs 
       List<string> IDs = (from xml in deserializedXML.Variable select xml.Id).ToList(); 
      } // Put a break-point here, then mouse-over IDs and you will see all your IDs... deserializedXML contains the entire object if you want anythin else .... 
     } 
     catch (Exception) 
     { 
      throw; 
     } 

Ich lese Ihren XML-Code aus einer Datei (xml.xml), die sich im Ordner application * .exe befindet, Sie müssen diese Lösung an Ihre spezifischen Anforderungen anpassen.

Ist das, was Sie brauchen ?. ...

 try 
     { 
      XmlSerializer DeserializerPlaces = new XmlSerializer(typeof(DeviceState)); 

      string html = string.Empty; 
      string url = @"https://<Your URL>"; 

      HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); 
      //request.AutomaticDecompression = DecompressionMethods.GZip; 

      using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) 
      using (Stream stream = response.GetResponseStream()) 
      using (StreamReader reader = new StreamReader(stream)) 
      { 
       DeviceState dezerializedXML = (DeviceState)DeserializerPlaces.Deserialize(reader); 
       //html = reader.ReadToEnd(); 
      } 
      //Console.WriteLine(html); 

     } 
     catch (System.Exception) 
     { 
      throw; 
     } 

Sie nennen würde, dass alle 5 Sekunden und die Benutzeroberfläche aktualisieren (von dezerializedXML Eigenschaften)

+0

Danke für die Antwort. Aber ich würde 1 dieser Datei (und ich habe viele) alle 5 Sekunden (HTTP GET) bekommen. Glauben Sie, dass dies die Geschwindigkeit der Lösung nicht beeinflussen würde? Es ist Teil des HMI-Dashboards und ich werde die Benutzeroberfläche basierend auf diesen Variablen aktualisieren. – Shahzad

+0

Möglicherweise müssen Sie mehr von Ihrem Code sehen. Habe meine Antwort aktualisiert ..... – Monty

+0

Ich habe ein Update für diesen Beitrag mit Ihren Vorschlägen veröffentlicht. Es tut so ziemlich alles, was ich brauchte. Hoffentlich dauert es auch für den Rest von xml-Diensten :) Danke. Ich werde Sie aktualisierte Antwort testen und melden Sie zurück – Shahzad

Verwandte Themen