XPath string to select a specific node with specific value c# - c#

I want to select a node where inner text of cat is 'PG' using XPath
<?xml version="1.0" encoding="utf-8"?>
<Students>
<student>
<name>Talha</name>
<cat>PG</cat>
</student>
<student>
<name>irfan</name>
<cat>UG</cat>
</student>
<student>
<name>Ali</name>
<cat>PG</cat>
</student>
<student>
<name>Umer</name>
<cat>UG</cat>
</student>
</Students>
Code which I tried is this
XmlElement xmldoc = (XmlElement)doc.DocumentElement
.SelectSingleNode("/Students/student/*[*[local-name()='cat']='PG']");

To select all the student nodes which sub-elements cat have the value 'PG' use this XPath expression
/Students/student[cat='PG']
To only get the first one use
/Students/student[cat='PG'][1]
So in the syntax of C# use
XmlElement xmldoc = (XmlElement)doc.DocumentElement.SelectSingleNode("/Students/student[cat='PG'][1]");

Related

Question with Linq on XML,At least one object must implement IComparable

string studentsXML =
#"<Students>
<Student>
<Name>Toni</Name>
<Age>21</Age>
<University>Yale</University>
<Semester>6</Semester>
<GPA>3.5</GPA>
</Student>
<Student>
<Name>Carla</Name>
<Age>17</Age>
<University>Yale</University>
<Semester>1</Semester>
<GPA>3.8</GPA>
</Student>
<Student>
<Name>Leyla</Name>
<Age>19</Age>
<University>Beijing Tech</University>
<Semester>3</Semester>
<GPA>3.0</GPA>
</Student>
<Student>
<Name>Frank</Name>
<Age>25</Age>
<University>Beijing Tech</University>
<Semester>10</Semester>
<GPA>2.0</GPA>
</Student>
<Student>
<Name>Ken</Name>
<Age>29</Age>
<University>Beijing Tech</University>
<Semester>10</Semester>
<GPA>4.0</GPA>
</Student>
</Students>";
**Above is the XML code and I'm trying to sort it in order of age using linq so it should be able to display name and age in order at the end.
Code below is showing error. Would appreciate it if someone could give me input on this.
I'm actually still learning right now and was trying out stuff but obviously it is not working. **
XDocument studentsXdoc1 = new XDocument();
studentsXdoc1 = XDocument.Parse(studentsXML);
var testing = from student in studentsXdoc1.Descendants("Student")
orderby student.Element("Age")
select new
{
Name = student.Element("Name"),
Age = student.Element("Age")
};
foreach(var i in testing)
{
Console.WriteLine(i);
}
Console.ReadKey();
Just add .Value to student.Element("Age") to get the value of the element
var testing = from student in studentsXdoc1.Descendants("Student")
orderby int.Parse(student.Element("Age").Value)
select new
{
Name = student.Element("Name").Value,
Age = student.Element("Age").Value
};
The value of age needs to be parsed when ordering by age.

c# How to use linq to get xml string by filtering some data?

I want to get xml string by filtering data. For example, I need to filter some students whose sex is female.
I need to use linq to xml to get xml string.
The following is my initial xml code and expected xml string.
Initial xml code:
<? xml version="1.0" encoding="utf-8"?>
<School>
<Student>
<Name>Test1</Name>
<Birthday>1997-02-23</Birthday>
<Id>1001</Id>
<Sex>male</Sex>
<ClassId>01</ClassId>
<Scorevalue>Net Revenue</Scorevalue>
</Student>
<Student>
<Name>Test1</Name>
<Birthday>1998-02-21</Birthday>
<Id>1002</Id>
<Sex>female</Sex>
<ClassId>02</ClassId>
<Scorevalue>Net Revenue</Scorevalue>
</Student>
<Student>
<Name>Test1</Name>
<Birthday>1997-02-24</Birthday>
<Id>1004</Id>
<Sex>male</Sex>
<ClassId>03</ClassId>
<Scorevalue></Scorevalue>
</Student>
</School>
Expected xml string:
<School>
<Student>
<Name>Test1</Name>
<Birthday>1998-02-21</Birthday>
<Id>1002</Id>
<Sex>female</Sex>
<ClassId>02</ClassId>
<Scorevalue>Net Revenue</Scorevalue>
</Student>
</School>
Use the following code.
XDocument doc = XDocument.Load(path);
foreach(var x in doc.Descendants("Student").Where(x => x.Element("Sex").Value == "female"))
{
Console.WriteLine(x.ToString());
}
You can get the xml string like this,
string path = "D:\\test.xml";
XDocument doc = XDocument.Load(path);
doc.Descendants("Student").Where(x =>x.Element("Sex").Value=="male").Remove();
Console.WriteLine(doc.ToString());

SelectSingleNode Node InnerText property not correct

I am attempting to get the value of a specific node for each parent element found.
In the example I want to return each students First Name.
Instead I am getting the first elements name in each instance. The InnerText of a Student is correct but the InnerText of FirstName is always Alex.
var xml = #"<School>
<Students>
<Student>
<FirstName>Alex</FirstName>
<LastName>Smith</LastName>
<Grade>11</Grade>
</Student>
<Student>
<FirstName>Joanne</FirstName>
<LastName>Robins</LastName>
<Grade>12</Grade>
</Student>
<Student>
<FirstName>Steve</FirstName>
<LastName>Baker</LastName>
<Grade>11</Grade>
</Student>
</Students>
<Teachers>
<Teacher>
<FirstName>George</FirstName>
<LastName>Roberts</LastName>
<Grade>11</Grade>
</Teacher>
<Teacher>
<FirstName>Amanda</FirstName>
<LastName>Walker</LastName>
<Grade>12</Grade>
</Teacher>
<Teacher>
<FirstName>Tracey</FirstName>
<LastName>Smith</LastName>
<Grade>12</Grade>
</Teacher>
</Teachers>
</School>";
var doc = new XmlDocument();
doc.LoadXml(xml);
var resourceTypeNodes = doc.GetElementsByTagName("Student");
var resourceTypesIterator = resourceTypeNodes.GetEnumerator();
while (resourceTypesIterator != null && resourceTypesIterator.MoveNext())
{
var resourceTypeNode = resourceTypesIterator.Current as XmlNode;
var typeNameElement = resourceTypeNode.SelectSingleNode("//FirstName");
Console.WriteLine(resourceTypeNode.InnerXml);
Console.WriteLine(typeNameElement.InnerText);
}
This is the output of the above code.
<FirstName>Alex</FirstName><LastName>Smith</LastName><Grade>11</Grade>
Alex
<FirstName>Joanne</FirstName><LastName>Robins</LastName><Grade>12</Grade>
Alex
<FirstName>Steve</FirstName><LastName>Baker</LastName><Grade>11</Grade>
Alex
What am I missing?
Because you're using //FirstName XPath expression, that will always return first node from root, it doesn't matter if you invoke on children. Just change this:
var typeNameElement = resourceTypeNode.SelectSingleNode("//FirstName");
To this:
var typeNameElement = resourceTypeNode.SelectSingleNode("FirstName");
Moreover is there any specific reason you're manually using IEnumerator? You may simplify your code with foreach:
foreach (XmlNode resourceTypeNode in doc.GetElementsByTagName("Student"))
{
var typeNameElement = resourceTypeNode.SelectSingleNode("FirstName");
Console.WriteLine(resourceTypeNode.InnerXml);
Console.WriteLine(typeNameElement.InnerText);
}

XMLNODE: how can i select this node with attribute in my xml

I have an xml with the following structure
<student>
<name fname="oliver">
</name>
<name fname="de">
</name>
<name fname="johnson">
</name>
</student>
my code is like this:
//after loading into an xmldocument called xmlrecord
XmlNode row = xmlRecord.SelectSingleNode("/student");
student.fname = row.SelectSingleNode("name[fname]");
But its not returning anything. Pls what is the best way to select the fname='johnson' node?
You want the fname attribute of the first <name> element, so you should write:
student.fname = row.SelectSingleNode("name/#fname");

Unable to extract value from XDocument using xpath

I have a simple xml of users. I have a StudentId, I just need to get the student name from the xml on the basis of studentid. Seems to be simple but I am unable to get it done using xpath.
Here's the xml:
<Students>
<Student>
<StudentId>1</StudentId>
<StudentName>Mad</StudentName>
</Student>
<Student>
<StudentId>2</StudentId>
<StudentName>Cad</StudentName>
</Student>
</Students>
Here's my code:
XDocument xmldoc = XDocument.Load(Server.MapPath("~/xmlsample.xml"));
string StudentId = "2"; // id to be selected
var username = xmldoc.XPathSelectElement("Students/Student/StudentName").Value;// Not sure how to use where condition here
You just need to filter by studentId. Should be:
var username = xmldoc.XPathSelectElement(String.Format("Students/Student[StudentId={0}]/StudentName", StudentId)).Value;

Categories