Yunus Emre Yüce
Yunus Emre Yüce

Reputation: 53

I'm confused by Linq XML query

Here is my XML sample. I want to select SystemSetting's value if ID = 123. But I can't figure out how. How can I select SystemSetting value if id's value equal to 123 ?

<?xml version="1.0" encoding="utf-8" ?>
<Private>
  <System>
    <ID>123</ID>
    <NAME>Test</NAME>
    <SystemSetting>128</SystemSetting>
    <SystemSettingCS>127</SystemSettingCS>
  </System> 
  <System>
    <ID>124</ID>
    <NAME>Test2</NAME>
    <SystemSetting>128</SystemSetting>
    <SystemSettingCS>127</SystemSettingCS>
  </System>
  <System>
    <ID>0</ID>
    <NAME>Test</NAME>   
    <SystemSetting>5</SystemSetting>
    <SystemSettingCS>250</SystemSettingCS>
  </System>
</Private>

Here's what I tried:

    var doc = XDocument.Load(Application.StartupPath+  @"\Settings.xml");
    var q = from Ana in doc.Descendants("Private")                   
            from sistem in Ana.Elements("System")                   
            where (int)sistem.Element("ID") == 123
            from assetText in Sistem.Elements("System")
            select assetText.Element("SystemSetting");

    MessageBox.Show(q.ToString());

thnx for help.

Upvotes: 4

Views: 108

Answers (5)

Chuck Savage
Chuck Savage

Reputation: 11955

Was a Linq question, but there is an alternate XPath approach, but the class defined below could work in either scenario.

Define a class to read from the parent System element:

public class XSystem
{
   public XSystem(XElement xSystem) { self = xSystem; }
   XElement self;

   public int Id { get { return (int)self.Element("ID"); } }
   public string Name { get { return self.Element("NAME").Value; } }
   public int SystemSetting { get { return (int)self.Element("SystemSetting"); } }
   public int SystemSettingCS { get { return (int)self.Element("SystemSettingCS"); } }
}

Then find your System element that has a child ID element of 123.

int id = 123;
string xpath = string.Format("//System[ID={0}", id);
XElement x = doc.XPathSelectElement(xpath);

Then plug it into the class:

XSystem system = new XSystem(x);

Then read the value you want:

int systemSetting = system.SystemSetting; 

XPath is defined with using System.Xml.XPath;

Upvotes: 0

L.B
L.B

Reputation: 116108

Xpath (System.Xml.XPath) can really help here

var system = doc.XPathSelectElement("//System[ID[text()='123']]");
var val = system.Element("SystemSetting").Value;

or with a single line

var s = (string)doc.XPathSelectElement("//System[ID[text()='123']]/SystemSetting");

Upvotes: 1

Jon Skeet
Jon Skeet

Reputation: 1500405

I think you're making this more complicated than you need to. I think you just need:

var query = doc.Descendants("Private") // Or just doc.Root
               .Elements("System")
               .Where(x => (int) x.Element("ID") == 123)
               .Select(x => x.Element("SystemSetting"))
               .FirstOrDefault();

That will select the first matching element, admittedly. The type of query is then XElement; if you take off the FirstOrDefault() part, it will return an IEnumerable<XElement>, for all matching elements.

If you want just the value instead of the element, you can change the Select to:

.Select(x => (string) x.Element("SystemSetting"))

or

.Select(x => x.Element("SystemSetting").Value)

(The first will return null if there's no SystemSetting element; the second will throw an exception.)

Upvotes: 2

Sergey Berezovskiy
Sergey Berezovskiy

Reputation: 236208

 var q = from s in doc.Descendants("System")  
         where (int)s.Element("ID") == 123        
         select (int)s.Element("SystemSetting");

And show result (q will have IEnumerable<int> type):

if (q.Any())
    MessageBox.Show("SystemSettings = " + q.First());
else
    MessageBox.Show("System not found");

Upvotes: 0

Simon West
Simon West

Reputation: 3788

Your almost there

var xmlFile = XElement.Load(@"c:\\test.xml");

var query =
  from e in xmlFile.Elements()
  where e.Element("ID").Value == "123"
  select e.Element("SystemSetting").Value;

Upvotes: 0

Related Questions