<Students>
<Student Name="John">
<Subject SubId="123" Content="History minor subject" Enrolled="true" Percentage="0"/>
<Subject SubId="146" Content="Math major Subject" Enrolled="true" Percentage="0"/>
</Student>
<Student Name="Jim">
<Subject SubId="564" Content="physics medium subject" Enrolled="true" Percentage="0"/>
<Subject SubId="324" Content="Chem small subject" Enrolled="true" Percentage="0"/>
</Student>
<Students>
Problem 1 - I want to search if the person name content John and content has "major" -- > return the Xelememt , I am trying with below query but it is not working for me.
String studentToSearch = "John" and string contentToSearch = "major"
IEnumerable<XElement> student = from st in rootElement.Descendants("Students").Elements("Student")
where st.Attribute("Name").Value.ToString() == studentToSearch && st.Element("Subject").Attribute("Content").Value.ToString().Contains(contentToSearch)
select st;
Problem 2 - I want to search if the person name content John and content has "major", if the percentage for that find it "0"-- > then update it to "80" percentage. Trying with below query
rootElement.Elements("Students")
.Where(x=> x.Element("Student").Value == studentToSearch)
.Where(a => a.Element("Subject").Attributes("Content").ToString().Contains(contentToSearch) && a.Element("Subject").Attribute("Percentage").Value == "0").FirstOrDefault()
.SetAttributeValue("Percentage", 80);
Any suggestion will be helpful ?
Why not just deserialize the xml? You need to use SelectMany.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create(FILENAME);
XmlSerializer serializer = new XmlSerializer(typeof(Students));
Students students = (Students)serializer.Deserialize(reader);
var johnMajor = students.Student.SelectMany(x => x.Subject.Where(y => y.Content.Contains("major")).Select(z => new { name = x.Name, Subject = z })).FirstOrDefault();
if (johnMajor.Subject.Percentage == 0) johnMajor.Subject.Percentage = 80;
}
}
public class Students
{
[XmlElement()]
public List<Student> Student { get; set; }
}
public class Student
{
[XmlAttribute()]
public string Name { get; set; }
[XmlElement]
public List<Subject> Subject { get; set; }
}
public class Subject
{
[XmlAttribute()]
public int SubId { get; set; }
[XmlAttribute()]
public string Content { get; set; }
[XmlAttribute()]
public Boolean Enrolled { get; set; }
[XmlAttribute()]
public int Percentage { get; set; }
}
}
Related
My goal is to extract the data from the XML. But I have some rather complex XML that is not easily converted to C sharp classes.
The XML looks like this:
<group.........>
<suite....>
<properties>
<property name=....../>
</properties>
<suite type="test">
<suite type="test1">
<suite...>
<suite...>
<suite...>
<case id="1000" name="example">
<properties>
<property ...../>
</properties>
</case>
<case.......>
<properties>
<property ...../>
</properties>
</case>
<case>
<properties>
<property .... />
</properties>
</case>
</suite>
</suite>
</suite>
</suite>
</suite>
</suite>
</group>
I have used an online xml to c sharp convert to create classes, but it does not seem to handle the XML structure correctly.
Update:
The XML comes from NUNIT3. It is the result of the UNIT3 console that is written to an XML document.
Update 2:
I am able to extract data using below code - don't know if there is a more elegant solution:
XElement resultFile = XElement.Load($"{resultFilePathList}");
var dataFromXML = (
from data in resultFile.Descendants("case")
select new
{
caseid = data.Attribute("id").Value,
name = data.Attribute("fullname").Value,
result = data.Attribute("result").Value,
duration = data.Attribute("duration").Value
}
);
Check this code, is as simple as this
using System.Xml.Serialization;
using System.IO;
.......
StreamReader streamer = new StreamReader("yourgroup.xml");
XmlSerializer serializer = new XmlSerializer(typeof(group));
group x = (group)serializer.Deserialize(streamer);
streamer.Close();
And you have do define your classes, somehow like this
public class group {List<suite> suite;}
public class suite
{
public List<suite> suite;
public List<property> properties;
}
Ok, you can add additional annotation if you need specific handling
For instance if there is "case" element, create your class with different name
public class xcase
{
public String id;
public String name;
public Property[] properties;...
}
public class suite
{
[XmlElement(ElementName = "case")]
public xcase[] cases {get; set; }
....
}
Try following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication120
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
XElement group = doc.Root;
Suite rootSuite = new Suite();
Suite.ReadXml(group, rootSuite);
}
}
public class Suite
{
public List<Suite> suites { get; set; }
public List<Case> cases { get; set; }
public Dictionary<string, string> properties { get; set; }
public string type { get; set; }
public static void ReadXml(XElement xparentSuite, Suite parentSuite)
{
foreach (XElement xSuite in xparentSuite.Elements("suite"))
{
parentSuite.type = (string)xSuite.Attribute("type");
if (parentSuite.suites == null) parentSuite.suites = new List<Suite>();
Suite newSuite = new Suite();
parentSuite.suites.Add(newSuite);
XElement properties = xSuite.Element("properties");
if (properties != null)
{
parentSuite.properties = properties.Elements("property")
.GroupBy(x => (string)x.Attribute("name"), y => (string)y)
.ToDictionary(x => x.Key, y => y.FirstOrDefault());
}
parentSuite.cases = xSuite.Elements("case").Select(x => new Case(x)).ToList();
ReadXml(xSuite, newSuite);
}
}
}
public class Case
{
public string id { get; set; }
public string name { get; set; }
public Dictionary<string, string> properties { get; set; }
public Case() { }
public Case(XElement _case)
{
id = (string)_case.Attribute("id");
name = (string)_case.Attribute("name");
properties = _case.Descendants("property")
.GroupBy(x => (string)x.Attribute("name"), y => (string)y)
.ToDictionary(x => x.Key, y => y.FirstOrDefault());
}
}
}
I'm trying to parse this XML Document:
<MPD>
<Period duration="PT0H3M1.63S" start="PT0S">
<AdaptationSet>
<ContentComponent contentType="video" id="1" />
<Representation bandwidth="4190760" codecs="avc1.640028" height="1080" id="1" mimeType="video/mp4" width="1920">
<BaseURL>car-20120827-89.mp4</BaseURL>
</Representation>
<Representation bandwidth="2073921" codecs="avc1.4d401f" height="720" id="2" mimeType="video/mp4" width="1280">
<BaseURL>car-20120827-88.mp4</BaseURL>
</Representation>
</AdaptationSet>
<AdaptationSet>
<ContentComponent contentType="audio" id="2" />
<Representation bandwidth="127236" codecs="mp4a.40.2" id="6" mimeType="audio/mp4" numChannels="2" sampleRate="44100">
<BaseURL>car-20120827-8c.mp4</BaseURL>
</Representation>
<Representation bandwidth="255236" codecs="mp4a.40.2" id="7" mimeType="audio/mp4" numChannels="2" sampleRate="44100">
<BaseURL>car-20120827-8d.mp4</BaseURL>
</Representation>
</AdaptationSet>
</Period>
</MPD>
using this C# code:
var rootDoc = new XmlDocument();
rootDoc.LoadXml(xmlString); // the one from above
var adaptationSets = rootDoc.GetElementsByTagName("AdaptationSet");
if (adaptationSets.Count > 0)
foreach (XmlNode adaptionSet in adaptationSets) // Loop through AdaptionSets
{
// Get the one Node in this AdaptionSet with the ContentComponent-Tag
var contentComponent = adaptionSet.SelectSingleNode("ContentComponent");
if (contentComponent != null)
{
// parse attributes
}
// Get All Nodes in this AdaptionSet with the Representation-Tag
var representations = adaptionSet.SelectNodes("Representation");
if(representations?.Count > 0)
foreach (XmlNode representation in representations)
{
// parse attributes of XmlNode
}
}
It all works except for the XPath queries. I tried a lot of variations with leading "/", "//", "./" and without any leading characters, but it just won't work. What am I doing wrong? I'm not using XPath on a regular basis and I couldn't find anything more than the leading characters I mentioned. Because I've seen it on a lot of other answers on this website I feel like I should mention that I'm explicitly looking for the XPath that will help me solve this, not some Linq variation or an entirely different approach.
Any help is greatly appreciated. Thanks in advance!
I think this solves your problem:
var rootDoc = new XmlDocument();
rootDoc.LoadXml(xmlString); // the one from above
var adaptationSets = rootDoc.SelectNodes("//AdaptationSet");
if (adaptationSets.Count > 0)
foreach (XmlNode adaptionSet in adaptationSets) // Loop through AdaptionSets
{
// Get the one Node in this AdaptionSet with the ContentComponent-Tag
var contentComponent = adaptionSet.SelectSingleNode("./ContentComponent");
if (contentComponent != null)
{
// parse attributes
}
// Get All Nodes in this AdaptionSet with the Representation-Tag
var representations = adaptionSet.SelectNodes("./Representation");
if (representations?.Count > 0)
foreach (XmlNode representation in representations)
{
// parse attributes of XmlNode
}
}
Try using xml linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
XElement period = doc.Descendants("Period").FirstOrDefault();
MPD mpd = new MPD();
mpd.duration = (string)period.Attribute("duration");
mpd.start = (string)period.Attribute("start");
mpd.adaptions = period.Elements("AdaptationSet").Select(x => new Adaption() {
contentType = (string)x.Element("ContentComponent").Attribute("contentType"),
id = (int)x.Element("ContentComponent").Attribute("id"),
representations = x.Elements("Representation").Select(y => new Representation() {
bandwidth = (int)y.Attribute("bandwidth"),
codecs = (string)y.Attribute("codecs"),
height = (int?)y.Attribute("height"),
id = (int)y.Attribute("id"),
mimeType = (string)y.Attribute("mimeType"),
width = (int?)y.Attribute("width"),
baseURL = (string)y.Descendants("BaseURL").FirstOrDefault()
}).ToList()
}).ToList();
}
}
public class MPD
{
public string duration { get; set; }
public string start { get; set; }
public List<Adaption> adaptions { get; set; }
}
public class Adaption
{
public string contentType { get; set; }
public int id { get; set; }
public List<Representation> representations { get; set; }
}
public class Representation
{
public int bandwidth { get; set; }
public string codecs { get; set; }
public int? height { get; set; }
public int id { get; set; }
public string mimeType { get; set; }
public int? width { get; set; }
public string baseURL { get; set; }
}
}
Let's say I want to parse following XML file:
<EmployeeDetails>
<Employee> //List of Employees
<Id>11</Id>
<name>a</name>
<Dependents> //List of Dependents of a single employee
<Dependent>
<name>a1</name>
<age>50</age>
</Dependent>
<Dependent>
<name>a2</name>
<age>52</age>
</Dependent>
</Dependents>
<Department> //Unique per Emp
<DeptId>1</DeptId>
<DeptName>D1</DeptName>
</Department>
</Employee>
<Employee>
-----
--------
</Employee>
</EmployeeDetails>
Following is the Class Structure for above file:
public class Employee
{
public int id {get; set;}
public string name {get; set;}
public List<Dependents> Dependents {get; set;}
public Department Department {get; set;}
}
public class Dependents
{
public string name {get; set;}
public int age {get; set;}
}
public class Department
{
public int DeptId {get; set;}
public string DeptName {get; set;}
}
Now, I want to parse above XML structure and I am able to do it for id and name of Employee but I am unable to parse further.
Let me show you what I've done so far :
public static void ParseXml()
{
string xmldoc = //let's assume I've data in this string
XDocument xdoc = new XDocument();
xdoc = XDocument.Parse(xmldoc);
var query = from d in xdoc.Root.Descendants("Employee")
select d;
List<Employee> lsEmp = new List<Employee>();
foreach (var q in query)
{
Employee obj = new Employee();
obj.Id = Convert.ToInt32(q.Element("Id").Value);
obj.name = q.Element("name").Value;
obj.Department = new Department();
obj.Dependents = new List<Dependents>();
// how to get data further?
lsEmp.Add(obj);
}
So I need help in order to parse XML data from these list of Dependents and Department object.
Following your own structure, here's the way to continue parsing the data you need.
// how to get data further?
var allDependents = q.Elements("Dependents").Elements("Dependent");
foreach (var b in allDependents)
{
Dependents d = new Dependents
{
age = Convert.ToInt32(b.Element("age").Value),
name = b.Element("name").Value
};
obj.Dependents.Add(d);
}
obj.Department.DeptId = Convert.ToInt32(q.Element("Department").Element("DeptId").Value);
obj.Department.DeptName = q.Element("Department").Element("DeptName").Value;
Notice that I have used .Elements("") to get all the child nodes under Dependents
Here is code using just linq and no for loops
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
string xml = File.ReadAllText(FILENAME);
ParseXml(xml);
}
public static void ParseXml(string xml)
{
XDocument xdoc = XDocument.Parse(xml);
List<Employee> employees = xdoc.Descendants("Employee").Select(x => new Employee () {
id = (int)x.Element("Id"),
name = (string)x.Element("Name"),
Department = x.Elements("Department").Select(y => new Department() { DeptId = (int)y.Element("DeptId"), DeptName = (string)y.Element("DeptName")}).FirstOrDefault(),
Dependents = x.Descendants("Dependent").Select(y => new Dependents() { age = (int)y.Element("age"), name = (string)y.Element("name")}).ToList()
}).ToList();
}
}
public class Employee
{
public int id { get; set; }
public string name { get; set; }
public List<Dependents> Dependents { get; set; }
public Department Department { get; set; }
}
public class Dependents
{
public string name { get; set; }
public int age { get; set; }
}
public class Department
{
public int DeptId { get; set; }
public string DeptName { get; set; }
}
}
Maybe this can help you:
XDocument xdoc = new XDocument();
xdoc = XDocument.Parse(xmldoc);
var query = from d in xdoc.Root.Descendants("Employee")
select d;
List<Employee> lsEmp = new List<Employee>();
foreach (var q in query)
{
Employee obj = new Employee();
obj.Id = Convert.ToInt32(q.Element("Id").Value);
obj.name = q.Element("name").Value;
obj.Department = new Department()
{
DeptName = q.Element("Department").Element("name").Value,
DeptId =
Convert.ToInt32(q.Element("Department").Element("age").Value)
};
obj.Dependents = new List<Dependents>();
foreach (var e in q.Element("Dependents").Elements("Dependent"))
{
var dependent = new Dependents()
{
name = e.Element("name").Value,
age = Convert.ToInt32(e.Element("age").Value)
};
obj.Dependents.Add(dependent);
}
lsEmp.Add(obj);
}
Sample XML:
<query yahoo:count="1" yahoo:created="2016-03-31T06:43:49Z" yahoo:lang="en-US">
<results>
<channel>
<item>
<yweather:condition code="28" date="Thu, 31 Mar 2016 08:00 AM SAST" temp="58" text="Mostly Cloudy"/>
</item>
</channel>
</results>
</query>
Code:
string weburl = "https://query.yahooapis.com/v1/public/yql?q=select%20item.condition%20from%20weather.forecast%20where%20woeid%20in%20%28select%20woeid%20from%20geo.places%281%29%20where%20text%3D%22Cape%20Town%22%29&format=xml&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys";
var xml = await new WebClient().DownloadStringTaskAsync(new Uri(weburl));
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
XmlElement root = doc.DocumentElement;
XmlNodeList nodes = root.SelectNodes("//query/results/channel/item");
foreach (XmlNode node in nodes)
{
MessageBox.Show(node.InnerXml);
}
I have been struggling to just get the temp and text outputed but I can't find way how to, this is as far as I got.
You can access XML attributes from XmlNode.Attributes property :
var condition = doc.SelectSingleNode("/query/results/channel/item/*");
MessageBox.Show(condition.Attributes["text"].Value);
MessageBox.Show(condition.Attributes["temp"].Value);
Try this....
Usings....
using System.IO;
using System.Net;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
Classes....
[XmlRoot(ElementName = "condition", Namespace = "http://xml.weather.yahoo.com/ns/rss/1.0")]
public class Condition
{
[XmlAttribute(AttributeName = "yweather", Namespace = "http://www.w3.org/2000/xmlns/")]
public string Yweather { get; set; }
[XmlAttribute(AttributeName = "code")]
public string Code { get; set; }
[XmlAttribute(AttributeName = "date")]
public string Date { get; set; }
[XmlAttribute(AttributeName = "temp")]
public string Temp { get; set; }
[XmlAttribute(AttributeName = "text")]
public string Text { get; set; }
}
[XmlRoot(ElementName = "item")]
public class Item
{
[XmlElement(ElementName = "condition", Namespace = "http://xml.weather.yahoo.com/ns/rss/1.0")]
public Condition Condition { get; set; }
}
[XmlRoot(ElementName = "channel")]
public class Channel
{
[XmlElement(ElementName = "item")]
public Item Item { get; set; }
}
[XmlRoot(ElementName = "results")]
public class Results
{
[XmlElement(ElementName = "channel")]
public Channel Channel { get; set; }
}
[XmlRoot(ElementName = "query")]
public class Query
{
[XmlElement(ElementName = "results")]
public Results Results { get; set; }
[XmlAttribute(AttributeName = "yahoo", Namespace = "http://www.w3.org/2000/xmlns/")]
public string Yahoo { get; set; }
[XmlAttribute(AttributeName = "count", Namespace = "http://www.yahooapis.com/v1/base.rng")]
public string Count { get; set; }
[XmlAttribute(AttributeName = "created", Namespace = "http://www.yahooapis.com/v1/base.rng")]
public string Created { get; set; }
[XmlAttribute(AttributeName = "lang", Namespace = "http://www.yahooapis.com/v1/base.rng")]
public string Lang { get; set; }
}
Code...
XmlDocument xmlDocument = new XmlDocument();
try
{
xmlDocument.Load("https://query.yahooapis.com/v1/public/yql?q=select%20item.condition%20from%20weather.forecast%20where%20woeid%20in%20%28select%20woeid%20from%20geo.places%281%29%20where%20text%3D%22Cape%20Town%22%29&format=xml&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys");
string XMLxmlDocument = xmlDocument.InnerXml.ToString();
byte[] BUFXML = ASCIIEncoding.UTF8.GetBytes(XMLxmlDocument);
MemoryStream ms1 = new MemoryStream(BUFXML);
XmlSerializer DeserializerPlaces = new XmlSerializer(typeof(Query));//, new XmlRootAttribute("Query"));
using (XmlReader reader = new XmlTextReader(ms1))
{
Query dezerializedXML = (Query)DeserializerPlaces.Deserialize(reader);
string temp = dezerializedXML.Results.Channel.Item.Condition.Temp;
string text = dezerializedXML.Results.Channel.Item.Condition.Text;
}// Put a break-point here, then mouse-over temp and text, you should have you values (dezerializedXML contains the entire object)
}
catch (System.Exception)
{
throw;
}
I used xml linq along with Regex. I had to fix issues with your xml. I think the main issue was the namespaces.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Text.RegularExpressions;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string xml =
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>" +
"<Root xmlns:yahoo=\"abc\" xmlns:yweather=\"def\">" +
"<query yahoo:count=\"1\" yahoo:created=\"2016-03-31T06:43:49Z\">" +
"yahoo:lang=\"en-US\"><results>" +
"<channel>" +
"<item>" +
"<yweather:condition>" +
"code=\"28\" date=\"Thu, 31 Mar 2016 08:00 AM SAST\" temp=\"58\" text=\"Mostly Cloudy\"/>" +
"</yweather:condition>" +
"</item>" +
"</channel>" +
"</results>" +
"</query>" +
"</Root>";
XDocument doc = XDocument.Parse(xml);
string innertext = doc.Descendants().Where(x => x.Name.LocalName == "condition").Select(y => y.Value).FirstOrDefault();
string pattern = "\\s?(?'name'[^=]+)=\"(?'value'[^\"]+)\"";
MatchCollection matches = Regex.Matches(innertext, pattern);
foreach (Match match in matches)
{
Console.WriteLine("Name : {0}, Value : {1}", match.Groups["name"].Value, match.Groups["value"].Value);
}
Console.ReadLine();
}
}
}
I have a DataContract class MyDataContract. I am serializing it to a XML file. Later, at a totally different "place" in my application I am loading this file. There I want to verify to load only, if the content of the file matches special conditions. Let's say I store a person and the association to the person's vehicle assuming a person can own just one vehicle. :-)
Here the DataContract classes:
namespace Test.DataContracts
{
[DataContract]
public class MyDataContract
{
[DataMember]
public string Identifier { get; set; }
[DataMember]
public Common.Person Person { get; set; }
[DataMember]
public Common.Vehicle Vehicle { get; set; }
}
}
namespace Test.DataContracts.Common
{
[DataContract]
public class Person
{
[DataMember]
public Global.Gender Gender { get; set; }
[DataMember]
public string Info { get; set; }
[DataMember]
public string Name { get; set; }
}
[DataContract]
public class Vehicle
{
[DataMember]
public string Info { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public string Vendor { get; set; }
}
}
namespace Test.DataContracts.Global
{
[DataContract]
public class Gender
{
[DataMember]
public int Type { get; set; }
[DataMember]
public string Name { get; set; }
}
}
Results in the following serialized XML:
<?xml version="1.0" encoding="utf-8"?>
<MyDataContract xmlns="http://schemas.datacontract.org/2004/07/Test.DataContracts" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Identifier>123456789</Identifier>
<Person xmlns:a="http://schemas.datacontract.org/2004/07/Test.DataContracts.Common">
<a:Gender xmlns:b="http://schemas.datacontract.org/2004/07/Test.DataContracts.Global">
<b:Name>Female</b:Name>
<b:Type>0</b:Type>
</a:Gender>
<a:Info>She is a beautiful lady.</a:Info>
<a:Name>Jane Doe</a:Name>
</Person>
<Vehicle xmlns:a="http://schemas.datacontract.org/2004/07/Test.DataContracts.Common">
<a:Info>A super great car.</a:Info>
<a:Name>Mustang 1983 Turbo GT</a:Name>
<a:Vendor>Ford</a:Vendor>
</Vehicle>
</MyDataContract>
Now I want to filter out only Female (Type = 0) persons that own any Ford (Vendor = Ford) vehicle. I tried the following, but it always results in false for the matches.
string path = #"c:\janedoe.xml";
var xmlDoc = new XmlDocument();
xmlDoc.Load(path);
XmlNodeList xNodes = xmlDoc.SelectNodes(#"//namespace::*[not(. = ../../namespace::*)]");
var xNamespaceManager = new XmlNamespaceManager(xmlDoc.NameTable);
foreach (XmlNode node in xNodes)
{
if (!string.IsNullOrWhiteSpace(xNamespaceManager.LookupNamespace(node.LocalName))) continue;
xNamespaceManager.AddNamespace(node.LocalName, node.Value);
}
using (var fs = new FileStream(path, FileMode.Open))
{
var xDocument = new XPathDocument(fs);
var xNavigator = xDocument.CreateNavigator();
XPathExpression exp1 = xNavigator.Compile(string.Format("MyDataContract/Person/Gender/Type/descendant::*[contains(text(), '{0}')]", "0"));
exp1.SetContext(xNamespaceManager);
XPathExpression exp2 = xNavigator.Compile(string.Format("MyDataContract/Vehicle/Vendor/descendant::*[contains(text(), '{0}')]", "Ford"));
exp2.SetContext(xNamespaceManager);
if (xNavigator.Matches(exp1) && xNavigator.Matches(exp2))
{
Console.WriteLine("File '{0}' indicates a female person that owns a vehicle of Ford.", path);
}
else
{
Console.WriteLine("File '{0}' has no matches (female and Ford).", path);
}
}
Can anyone help?
UPDATE 1 - I have changed the code using XmlNamespaceManager. But still results in false when executing xNavigator.Matches(exp1).
If you have XDocument it is easier to use LINQ-to-XML:
var xdoc = XDocument.Load(memorystream);
// Making it simple, grab the first
var type = xdoc.Descendants(XName.Get("Type","http://schemas.datacontract.org/2004/07/Test.DataContracts.Global")).FirstOrDefault();
var vendor = xdoc.Descendants(XName.Get("Vendor", "http://schemas.datacontract.org/2004/07/Test.DataContracts.Common")).FirstOrDefault();
string path = "blah";
if (type != null && type.Value == "0" && vendor != null && vendor.Value == "Ford")
{
Console.WriteLine("File '{0}' indicates a female person that owns a vehicle of Ford.", path);
}
else
{
Console.WriteLine("File '{0}' has no matches (female and Ford).", path);
}
If you are sure that XPath is the only solution you need:
using System.Xml.XPath;
var document = XDocument.Load(fileName);
var namespaceManager = new XmlNamespaceManager(new NameTable());
namespaceManager.AddNamespace("a", "http://schemas.datacontract.org/2004/07/Test.DataContracts.Global");
var name = document.XPathSelectElement("path", namespaceManager).Value;