2016-07-16 4 views
0

Ich habe eine XML-Code, der wie folgt aussieht:LINQ to XML - Wie kann ich auf innere Tags in einem XML effizient zugreifen?

<?xml version="1.0" encoding="utf-8" ?> 
<root> 
    <data> 
    <dataname>A</dataname> 
    <property> 
     <name>One</name> 
     <value>1</value> 
    </property> 
    <property> 
     <name>Two</name> 
     <value>2</value> 
    </property> 
    </data> 
    <data> 
    <dataname>B</dataname> 
    <property> 
     <name>One</name> 
     <value>11</value> 
    </property> 
    <property> 
     <name>Two</name> 
     <value>22</value> 
    </property> 
    </data> 
</root> 

Ich versuche, eine Funktion in Visual Studio (C#) zu schreiben, die die value Teil von einem name - value Paar zurückgibt. Bisher konnte ich dies erreichen mit der folgenden (ich weiß, gibt es derzeit keinen Fehler darin Prüfung):

//private static XElement xml = new XElement("root"); 
//xml = XElement.Load("Defaults.xml"); -> this happens on program initialization 
// The program accesses it several times, so I'm keeping it in the memory to avoid excess HDD usage 

public int GetDefaultValue(string dataBlock, string propName) 
{ 
    var xx = 
     from first in xml.Elements("data") 
     where (string)first.Element("dataname") == dataBlock 
     select first; 

    var yy = 
     from second in xx.Elements("property") 
     where (string)second.Element("name") == propName 
     select second; 

    return int.Parse(yy.First().Element("value").Value); 
} 

Ich denke, das sehr schlecht aussieht und nach einer Tonne MSDN über LINQ Lese to XML I don‘ Ich denke, ich bin näher daran, dies zu einem besseren Code zu machen. Immer wenn ich dies mit einer einzigen Variable versuchte, bekam ich nie das, wonach ich suchte.

Kann mir bitte jemand helfen, dies einfacher zu machen? (So ​​kann ich lernen, was ich falsch gemacht habe)

Antwort

1

Sie können tun, dass in einer Abfrage:

public int GetDefaultValue(string dataBlock, string propName) 
{ 
    var val = 
      from data in xml.Elements("data") 
      where (string)data.Element("dataname") == dataBlock 
      from property in data.Elements("property") 
      where (string)property.Element("name") == propName 
      select property.Element("value"); 

    return (int)val.First(); 
} 
+0

Vielen Dank! Seltsamerweise, als ich etwas Ähnliches versuchte, funktionierte es nicht für mich. –

1

Versuchen Sie, diese

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Xml; 
using System.Xml.Linq; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Test test = new Test(); 
      int results = test.GetDefaultValue("A", "One"); 
     } 
    } 
    public class Test 
    { 
     const string FILENAME = @"c:\temp\test.xml"; 
     XDocument xml = null; 
     public Test() 
     { 
      xml = XDocument.Load(FILENAME); 
     } 


     public int GetDefaultValue(string dataBlock, string propName) 
     { 

      return xml.Descendants("data") 
       .Where(x => (string)x.Element("dataname") == dataBlock) 
       .Descendants("property") 
       .Where(y => (string)y.Element("name") == propName) 
       .Select(z => (int)z.Element("value")).FirstOrDefault(); 

     } 
    } 
} 
+0

Danke! Das funktioniert sehr gut, aber ich kenne mich noch nicht so gut mit Lambda-Ausdrücken aus. Trotzdem, sehr geschätzt! –

0

Für die VB'ers, die das gleiche Problem haben könnte.

Public Function GetDefaultValue(dataBlock As String, propName As String) As Integer 
    'note - returns zero if not found 
    Return (From d In xe.Elements 
      Where d.<dataname>.Value = dataBlock 
      From p In d.<property> 
      Where p.<name>.Value = propName 
      Select CInt(p.<value>.Value) Take 1).FirstOrDefault 
End Function 

Mit Hilfe dieser Daten

Dim xe As XElement = <root> 
         <data> 
          <dataname>A</dataname> 
          <property> 
           <name>One</name> 
           <value>1</value> 
          </property> 
          <property> 
           <name>Two</name> 
           <value>2</value> 
          </property> 
         </data> 
         <data> 
          <dataname>B</dataname> 
          <property> 
           <name>One</name> 
           <value>11</value> 
          </property> 
          <property> 
           <name>Two</name> 
           <value>22</value> 
          </property> 
         </data> 
        </root>