Need help in properly writing an XML LINQ query - c#

XML Snippet
<GameList>
<Game>
<GameDefinitiongameID>{1b2e4ff7-ddd3-4fe3-9fdf-6b2ee240d18c}</GameDefinitiongameID>
<WMID>{01bc5c01-923d-4efb-bba6-49e93b2694ab}</WMID>
<VersionNumberversionNumber>1.0.0.0</VersionNumberversionNumber>
<Title>JamesBond007:Nightfire</Title>
<GameExecutablepath>\easupport\go_ez.exe</GameExecutablepath>
<GameExecutablepath>\easupport\jamesbond007nightfire_code.exe</GameExecutablepath>
<GameExecutablepath>\easupport\jamesbond007nightfire_ereg.exe</GameExecutablepath>
<GameExecutablepath>\easupport\jamesbond007nightfire_ez.exe</GameExecutablepath>
<GameExecutablepath>jamesbond007nightfire_uninst.exe</GameExecutablepath>
<GameExecutablepath>unwise.exe</GameExecutablepath>
<RatingratingID>{CEC5DB5A-B4C9-4809-96C6-39CE715E4790}</RatingratingID>
<ratingSystemID>{36798944-B235-48ac-BF21-E25671F597EE}</ratingSystemID>
<DescriptordescriptorID>{F110F831-9412-40c9-860A-B489407ED374}</DescriptordescriptorID>
<RatingratingID>{18CD34B7-7AA3-42b9-A303-5A729B2FF228}</RatingratingID>
<ratingSystemID>{768BD93D-63BE-46A9-8994-0B53C4B5248F}</ratingSystemID>
<DescriptordescriptorID>{B54162A2-F67F-46dc-9ED5-F6067520EC94}</DescriptordescriptorID>
<DescriptordescriptorID>{BE562A5F-2A80-4c28-9752-74C696E2ABAF}</DescriptordescriptorID>
</Game>
and so on.
I used the following to query this file
Dim members = From m In GameXml.Element("GameList").Elements("Game")
Where m.Element("Title").Value.ToLower.Contains(Name) = True
Select m.Descendants
"Name" is the variable containing the search string.
Now, how to I get all the info (as array of strings or any other parse-able format) from the "members" variable.
I am new to XML and LINQ.
I am OK with both C# and VB.Net.

If you don't know what exact properties it has you can do this:
dynamic members = from m In GameXml.Element("GameList").Elements("Game")
where m.Element("Title").Value.ToLower.Contains(Name) = True
select m;
now you can use: members.ratingSystemID
But if you know the properties you can create a class like:
public class Game{
public string Title{set; get; }
public string Name {get; set;}
.
.
.
}
and then:
List<Game> members = from m In GameXml.Element("GameList").Elements("Game")
where m.Element("Title").Value.ToLower.Contains(Name) = True
select new {Title = m.Title, Name = m.Name, ...};
so you can use it like Members[0].Title

Assuming you want to get Game node, you're so close:
Dim members = From m In GameXml.Element("GameList").Elements("Game")
Where m.Element("Title").Value.ToLower.Contains(Name) = True
Select m.Descendants("Game")
or (C#):
var members = GameXml.Descendants("Game")
.Where(g=>g.Element("Title").Value.ToLower().Contains("Whatever"));

Related

C# Console App - LINQ to find matching values between two IEnumerables

I'm having some issues construction a LINQ query to find MATCHING values in two IEnumerables I have from CSV files and outputting those matching values to another list for some bookkeeping later on in my application.
My classes for the IEnumerables and the related code (using CSVHelper) to read the CSVs into the IEnumerables are below. Any input on where to begin, LINQ query wise, to find those matching values and output to a list? I'm relatively new to LINQ (usually use SQL in the backend) and I'm finding it a bit difficult to do exactly what I want to.
CLASSES:
class StudentSuccessStudents
{
[CsvColumn(Name ="StudentID", FieldIndex = 1)]
public string StudentID { get; set; }
}
class PlacementStudents
{
[CsvColumn(Name = "StudentId", FieldIndex = 1)]
public string StudentId { get; set; }
}
PROGRAM:
CsvFileDescription inputCsvStuSuccess = new CsvFileDescription
{
SeparatorChar = ',',
FirstLineHasColumnNames = true,
EnforceCsvColumnAttribute = false
};
CsvContext ccStuSuccess = new CsvContext();
CsvFileDescription inputCsvStuScores = new CsvFileDescription
{
SeparatorChar = ',',
FirstLineHasColumnNames = false,
EnforceCsvColumnAttribute = true
};
CsvContext ccStuScores = new CsvContext();
IEnumerable<StudentSuccessStudents> students = ccStuSuccess.Read<StudentSuccessStudents>(filePath, inputCsvStuSuccess);
IEnumerable<PlacementStudents> outputStudents = ccStuScores.Read<PlacementStudents>(csvPath, inputCsvStuScores);
Any suggestions on how to get all my "StudentID" fields in the first list that match a "StudentId" in the second one to output to another list with LINQ? I basically need to have that "matching" list so I can safely ignore those values elsewhere.
You could always use the SQL syntax of Linq like shown below. This way it looks more like something you're use to, and gets you the duplicate values you need. Also looks more readable (in my opinion) too.
var duplicates = from success in students
join placement in outputStudents on success.StudentID equals placement.StudentId
select success.StudentID;
This is a linq operator to do this functionality called Intersect so
If they were both the same type you could do this
var result = students.Intersect(outputStudents);
Which should be the fastest way.
Since they are different types you do this
var result = students.Intersect(outputStudents.Select(x => new StudentSuccessStudent(x.id) );
basically you create a new list of the correct type dynamically
This is an example where inheritance or interfaces are powerful. If they both inherited from the same type then you could intersect on that type and C# would solve this problem super fast.

Can't Get IEnumerable of Inherited Class in LINQ Query

I am trying to convert some code from VB over to C# and have had an extremely hard time with this particular LINQ query. First I'll show the classes:
Public Class CompanyData
Property CompanyID As String = ""
Property VendorNumber As String = ""
Property VendorName As String = ""
End Class
Public Class MultiCompData
Inherits CompanyData
Property ExpCompanyId As String = ""
End Class
Then in the VB example what it does is Group all into MultiCompData in a multiCompGroup field, foreach through it and add to a different list of CompanyData if ExpCompanyId is null/empty. Code:
Sub ProcessMultiCompData(multiCompDataJEs As IEnumerable(Of MultiCompData), ByRef multiCompData As List(Of CompanyData), ByRef undeterminedDists As List(Of CompanyData))
Dim multiCompGroups =
From m In multiCompDataJEs
Group m By m.ExpCompanyId,
m.VendorNumber,
m.VendorName
Into Group
For Each grp In multiCompGroups
If grp.ExpCompanyId = "" Then
undeterminedDists.AddRange(grp.Group)
In the foreach, grp has the following properties - ExpCompanyId, VendorNumber, VendorName and Group (which is the part I can't replicate in C#) Group being an IEnumerable. Is it not possible to add that IEnumerable in C# to multiCompGroups?? I have tried:
var multiCompGroups = from m in multiCompDataJEs group by new {m.ExpCompanyiD, m.VendorNumber, m.VendorName} into multiGroups
multiGroups doesn't show up as an IEnumerable in my grp value when I get to the foreach, i've also tried it this way:
var multiCompGroups = multiCompDataJEs.GroupBy(x => new {m.ExpCompanyId, m.VendorNumber, m.VendorName}).Select(y => new {y.Key.ExpCompanyId, y.Key.VendorNumber, y.Key.VendorName}).ToList();
Both are producing the same thing. I have the 3 properties show up when I do grp. but the "Into Group" (grp.Group in the VB code above) doesn't show up in C#. Is it even possible to do?
The C# you're looking for is:
var multiCompGroups =
from m in multiCompDataJEs
group m by new {m.ExpCompanyiD, m.VendorNumber, m.VendorName} into multiGroups
select multiGroups;
foreach(var grp in multiCompGroups)
{
if(grp.Key.ExpCompanyId == "")
{
undeterminedDists.AddRange(grp);
}
}

How can I get the items from a list of string that contain a determinate string value in asp.net?

I have this list:
Spain_Finance
France_Sport
Spain_Politics
USA_Science
USA_Finance
I use this code to check if the list contains a determinate value:
Dim namecountry As String = "Spain"
Dim listcontainscountry As Boolean = mylistofcountries.Any(Function(l) l.Contains(namecountry))
If listcontainscountry = True Then
' Here I need to get the elements from the list that contains Spain
End If
So after doing this inside the if statement I need to get the elements from the list that contains Spain
The result will be this:
Spain_Finance
Spain_Politics
I looking for a simple code to do this, I can do a foreach and compare the name from country with the item list, but I want to know is there another way more simple, this is for learn, I appreciate your contribution, thanks
You can use Where instead for Any so the code will be like the following:
Dim namecountry As String = "Spain"
Dim listcontainscountry = mylistofcountries.Where(Function(l) l.Contains(namecountry)).ToList()
Since the question is tagged to c# also, this Example will help you, that is the code will be :
List<string> countryList = new List<string>() { "Spain_Finance", "France_Sport", "Spain_Politics", "USA_Science", "USA_Finance" };
string namecountry = "Spain";
List<string> SelectedCountries = countryList.Where(x => x.Contains(namecountry)).ToList();
if(SelectedCountries.Count>0)
Console.WriteLine("Selected Countries : {0}", String.Join(",",SelectedCountries));
else
Console.WriteLine("No Matches ware found");
update: You can use Select followed by Where and .SubString the code will be like this
List<string> SelectedCountries = countryList.Where(x => x.Contains(namecountry))
.Select(x=>x.Substring(x.IndexOf("_")+1))
.ToList();

Updating entire node with mutating cypher in Neo4jclient

I need to update all the properties of a given node, using mutating cypher. I want to move away from Node and NodeReference because I understand they are deprecated, so can't use IGraphClient.Update. I'm very new to mutating cypher. I'm writing in C#, using Neo4jclient as the interface to Neo4j.
I did the following code which updates the "Name" property of a "resunit" where property "UniqueId" equals 2. This works fine. However,
* my resunit object has many properties
* I don't know which properties have changed
* I'm trying to write code that will work with different types of objects (with different properties)
It was possible with IGraphClient.Update to pass in an entire object and it would take care of creating cypher that sets all properies.
Can I somehow pass in my object with mutating cypher as well?
The only alternative I can see is to reflect over the object to find all properties and generate .Set for each, which I'd like to avoid. Please tell me if I'm on the wrong track here.
string newName = "A welcoming home";
var query2 = agencyDataAccessor
.GetAgencyByKey(requestingUser.AgencyKey)
.Match("(agency)-[:HAS_RESUNIT_NODE]->(categoryResUnitNode)-[:THE_UNIT_NODE]->(resunit)")
.Where("resunit.UniqueId = {uniqueId}")
.WithParams(new { uniqueId = 2 })
.With("resunit")
.Set("resunit.Name = {residentialUnitName}")
.WithParams(new { residentialUnitName = newName });
query2.ExecuteWithoutResults();
It is indeed possible to pass an entire object! Below I have an object called Thing defined as such:
public class Thing
{
public int Id { get; set; }
public string Value { get; set; }
public DateTimeOffset Date { get; set; }
public int AnInt { get; set; }
}
Then the following code creates a new Thing and inserts it into the DB, then get's it back and updates it just by using one Set command:
Thing thing = new Thing{AnInt = 12, Date = new DateTimeOffset(DateTime.Now), Value = "Foo", Id = 1};
gc.Cypher
.Create("(n:Test {thingParam})")
.WithParam("thingParam", thing)
.ExecuteWithoutResults();
var thingRes = gc.Cypher.Match("(n:Test)").Where((Thing n) => n.Id == 1).Return(n => n.As<Thing>()).Results.Single();
Console.WriteLine("Found: {0},{1},{2},{3}", thingRes.Id, thingRes.Value, thingRes.AnInt, thingRes.Date);
thingRes.AnInt += 100;
thingRes.Value = "Bar";
thingRes.Date = thingRes.Date.AddMonths(1);
gc.Cypher
.Match("(n:Test)")
.Where((Thing n) => n.Id == 1)
.Set("n = {thingParam}")
.WithParam("thingParam", thingRes)
.ExecuteWithoutResults();
var thingRes2 = gc.Cypher.Match("(n:Test)").Where((Thing n) => n.Id == 1).Return(n => n.As<Thing>()).Results.Single();
Console.WriteLine("Found: {0},{1},{2},{3}", thingRes2.Id, thingRes2.Value, thingRes2.AnInt, thingRes2.Date);
Which gives:
Found: 1,Foo,12,2014-03-27 15:37:49 +00:00
Found: 1,Bar,112,2014-04-27 15:37:49 +00:00
All properties nicely updated!

Apply some field description using an XML

I need a verry especific format for each field of MyObject class
public class MyObject{
public Long Amount {get; set}
public Long FiscalAmount {get; set;}
// .... A lot more of fields
}
For example,
if MyObject.Amount is 5000 the expected result is 00005000.
if MyObject.FiscalAmount is 23 the expected result is 000023
In order to accomplished this, I have defined an XML file:
<FieldDescriptionXML>
<FielDefinition>
<Name>Amount</Name>
<FillWith>0</FillWith>
<Lenght>8</Lenght>
</FielDefinition>
<FielDefinition>
<Name>FiscalAmount</Name>
<FillWith>0</FillWith>
<Lenght>6</Lenght>
</FielDefinition>
.... A lot more of fields
<FieldDescriptionXML>
Then I use the following code to get MyObject fields with the desired output
MyObject myObject = new MyObject();
myObject.Amount = 5000;
...
// Gets the xml definition
// I deserialize the previous XML file and name it FieldDescription
List<FieldDescription> fieldDescriptionList = DeserializeXML(XMLFilePath);
FieldDescription fieldDescription = fieldDescriptionList.Find(x => x.Name == "Amount");
// Apply the field definition and returns a string.
// For this I use a private method called ApplyXMLFielDefinition
// where I got how many spaces the result should be filled
string result = ApplyXMLFielDefinition(myObject.Amount,fieldDescription);
Console.Writeline(result) // prints 00005000
// Now same code for MyObject.FiscalAmount
As you see, I got the desired output, but I had to do it one by one repeating the code.
Is there any other other better approached you can share?, thanks.
Environment: C# 4.0
If I am reading your question correctly you will have a list of elements you want populated from a large xml collection. Have you tried LinqToXml
var x = (from target in xmlDoc.Decendants("FielDefinition")
select (int) target.Element("FillWith").value()
where target.Element("Name").Value.tolower() == "amount")).ToList();
That will return a list<int>

Categories