I have an XML file as string.
I want to filter the value from this string that is located between two given strings (between two tags).
These two strings (tags) can occur more than once.
My string is:
public string text = "<?xml version="1.0" encoding="utf-8"?> <Userlist> <User1 userid="123" agreement="true"> <firstname>Daniel</firstname> <lastname>Brown</lastname> </User1> <User2 userid="124" agreement="false"> <firstname>Charlie</firstname> <lastname>Walsh</lastname> </User2> </Userlist>"
e.g. I would like to have all strings from the following string that are between <firstname> and </firstname>.
Thank`s a lot.
You should use XML library to parse xml. Not string methods. To get unique items you should use GroupBy and then take first item. A Group by produces a two dimensional array List>. GroupBy creates unique keys and then First get one item from each key. See code below which uses xml linq
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
string text = File.ReadAllText(FILENAME);
XDocument doc = XDocument.Parse(text);
List<User> users = doc.Root.Elements().Select(x => new User
{
id = (string)x.Attribute("userid"),
agreement = (Boolean)x.Attribute("agreement"),
firstname = (string)x.Element("firstname"),
lastname = (string)x.Element("lastname")
}).ToList();
List<User> distinct = users.GroupBy(x => x.id)
.Select(x => x.First())
.ToList();
}
}
public class User
{
public string id { get; set; }
public Boolean agreement { get; set; }
public string firstname { get; set; }
public string lastname { get; set; }
}
}
If you are looking for repetition of words, replace characters like < / "" > by space character. So that way you end up with words separated by space. Now split the text in array and use Dictionary to count each occurrence by something like code below
text = text.Replace('<', ' ');
text = text.Replace('>', ' ');
text = text.Replace('\"', ' ');
text = text.Replace('?', ' ');
text = text.Replace('=', ' ');
text = text.Replace('/', ' ');
var textAr = text.Split(' ');
var textDict = new Dictionary<string, int>();
foreach(var word in textAr)
{
if(textDict.ContainsKey(word))
{
textDict[word]++;
}
else
{
textDict.Add(word, 1);
}
}
Console.WriteLine("string: Repetition");
foreach (var key in textDict.Keys)
{
if (!String.IsNullOrWhiteSpace(key) && textDict[key] > 1)
{
Console.WriteLine(key + ": " + textDict[key]);
}
}
Output I get is
string: Repetition
Userlist: 2
User1: 2
userid: 2
agreement: 2
firstname: 4
lastname: 4
User2: 2
Related
I'm pulling data from excel and want to join multiple columns in to one and separate them by a comma. This columns share the same "Part Number" and If you look at the table under the "description code" FAB, It has multiple columns for the same code and I want to join them into one. My current code only pulls one of the columns.
Any help or suggestions is greatly appreciated
TABLE
Bag["Features"] = Lookup.GetLookup("Eibach-C1")
.Where(x=> x["E05"] == "FAB")
.ToDictionary(x => new Tuple<string, string>(x["B15"], x["C05"]));
var C1CodeKey = new Tuple <string, string>(In["B15"], "FAB");
if(Bag["C1Codes"].ContainsKey(C1CodeKey))
{
value = Bag["C1Codes"][C1CodeKey]["C10"];
}
else
{
value = "";
}
High level, I think you should create a class to store the Excel data.
Then read in the Excel data and deserialize to a List<PartData>
Then use Linq to shape the List:
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
var inData = new List<PartData>{
new PartData{
PartNumber = "0175.225.0150",
DescriptionCode = "DES",
Description = "EIBACK LINEAR TENDER SPRING"
},
new PartData{
PartNumber = "0175.225.0150",
DescriptionCode = "FAB",
Description = "Available in linear or progressive rates"
},
new PartData{
PartNumber = "0175.225.0150",
DescriptionCode = "FAB",
Description = "Each spring individually tested"
}
};
var shapedData = inData.GroupBy(i => new{i.PartNumber, i.DescriptionCode})
.Select(i=> new{
PartNumber = i.Key.PartNumber,
DescriptionCode = i.Key.DescriptionCode,
Description = string.Join(", ", i.Select(j => j.Description))
});
foreach(var dataItem in shapedData){
Console.WriteLine(dataItem);
}
}
}
public class PartData{
public string PartNumber {get;set;}
public string DescriptionCode {get;set;}
public string Description {get;set;}
}
Output:
{ PartNumber = 0175.225.0150, DescriptionCode = DES, Description = EIBACK LINEAR TENDER SPRING }
{ PartNumber = 0175.225.0150, DescriptionCode = FAB, Description = Available in linear or progressive rates, Each spring individually tested }
see:
https://dotnetfiddle.net/CGN7qy
Hi I am fairly new to coding, I have a piece of code that searches for a string and replaces it with another string like so:
var replacements = new[]{
new{Find="123",Replace="Word one"},
new{Find="ABC",Replace="Word two"},
new{Find="999",Replace="Word two"},
};
var myLongString = "123 is a long 999 string yeah";
foreach(var set in replacements)
{
myLongString = myLongString.Replace(set.Find, set.Replace);
}
If I want to use a CSV file that contains a lot of words and their replacements, for example, LOL,Laugh Out Loud, and ROFL, Roll Around Floor Laughing. How would I implement that?
Create a text file that looks like (you could use commas, but I like pipes (|)):
123|Word One
ABC|Word Two
999|Word Three
LOL|Laugh Out Loud
ROFL|Roll Around Floor Laughing
Then create a tiny helper class:
public class WordReplace
{
public string Find { get; set; }
public string Replace { get; set; }
}
And finally, call this code:
private static string DoWordReplace()
{
//first read in the data
var fileData = File.ReadAllLines("WordReplace.txt");
var wordReplacePairs = new List<WordReplace>();
var lineNo = 1;
foreach (var item in fileData)
{
var pair = item.Split(new[] {'|'}, StringSplitOptions.RemoveEmptyEntries);
if (pair.Length != 2)
{
throw new ApplicationException($"Malformed file, line {lineNo}, data = [{item}] ");
}
wordReplacePairs.Add(new WordReplace{Find = pair[0], Replace = pair[1]});
++lineNo;
}
var longString = "LOL, 123 is a long 999 string yeah, ROFL";
//now do the replacements
var buffer = new StringBuilder(longString);
foreach (var pair in wordReplacePairs)
{
buffer.Replace(pair.Find, pair.Replace);
}
return buffer.ToString();
}
The result is:
Laugh Out Loud, Word One is a long Word Three string yeah, Roll Around Floor Laughing
I have a string that looks like that:
random text 12234
another random text
User infos:
User name : John
ID : 221223
Date : 23.02.2018
Job: job1
User name : Andrew
ID : 378292
Date : 12.08.2017
Job: job2
User name : Chris
ID : 930712
Date : 05.11.2016
Job : job3
some random text
And this class:
class User
{
public string UserName { get; set; }
public string ID { get; set; }
public string Date { get; set; }
public string Job { get; set; }
public User(string _UserName, string _ID, string _Date, string _Job)
{
UserName = _UserName
ID = _ID;
Date = _Date;
Job = _Job;
}
}
And I want to create a List of Users with informations from that string.
I have tried doing that:
List<User> Users = new List<User>();
string Data = (the data above)
string[] lines = Data.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
List<string> UserNames = new List<string>();
List<string> IDs = new List<string>();
List<string> Dates = new List<string>();
List<string> Jobs = new List<string>();
foreach (var line in lines)
{
if (line.StartsWith("User name : "))
{
UserNames.Add(Line.Remove(0, 12));
}
if (Line.StartsWith("ID : "))
{
IDs.Add(Line.Remove(0, 5));
}
if (Line.StartsWith("Date : "))
{
Dates.Add(Line.Remove(0, 7));
}
if (Line.StartsWith("Job : "))
{
Jobs.Add(Line.Remove(0, 6));
}
}
var AllData = UserNames.Zip(IDs, (u, i) => new { UserName = u, ID = i });
foreach (var data in AllData)
{
Users.Add(new User(data.UserName, data.ID, "date", "job"));
}
But I can only combine two lists using this code. Also, I have more than 4 values for each user (the string above was just a short example) .
Is there a better method? Thanks.
Since it seems to be always 4 lines of information you could go in steps of 4 with a loop through the splitted array lines. At each step you would split by colon : and collect the last item, which is the desired value:
EDIT: In this case I would suggets to look for the START of the data.
int startIndex = Data.IndexOf("User name");
EDIT 2:
also ends with another line of text
then you can use LastIndexOf to find the end of the important information:
int endIndex = Data.LastIndexOf("Job");
int lengthOfLastLine = Data.Substring(endIndex).IndexOf(Environment.NewLine);
endIndex += lengthOfLastLine;
and then simply take a SubString from the startindex on until the end
string [] lines = Data.Substring(startIndex, endIndex - startIndex)
.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
List<User> allUsers = new List<UserQuery.User>();
for (int i = 0; i < lines.Length; i += 4)
{
string name = lines[i].Split(':').Last().Trim();
string ID = lines[i + 1].Split(':').Last().Trim();
string Date = lines[i + 2].Split(':').Last().Trim();
string Job = lines[i + 3].Split(':').Last().Trim();
allUsers.Add(new User(name, ID, Date, Job));
}
Ahhh, and you should Trim the spaces away.
This solution should be readable. The hard coded step size of 4 is actually annoying in my solution
Disclaimer: This solution works only as long as the format does not change. If the order of the lines should change, it will return false results
Instead of checking each line to add each of them to a a list, you can create your list of User directly. There you go:
Split by double new line
Split by new line
Build each User
Code:
var users = data.Split(new[] {"\n\n" }, StringSplitOptions.None).Select(lines =>
{
var line = lines.Split(new[] { "\n" }, StringSplitOptions.None);
return new User(line[0].Substring(11), line[1].Substring(4), line[2].Substring(6), line[3].Substring(5));
});
Try it online!
As #Mong Zhu answer, remove everything before and after. A this point, this is another question I wont try to solve. Remove the noise before and after then parse your data.
For a robust, flexible and self-documenting solution that will allow you to easily add new fields, ignore all the extraneous text and also cater for variations in your file format (this seems to be the case with, for example, no space in "ID:" only in the 3rd record), I would use a Regex and some LINQ to return a collection of records as follows:
using System.Text.RegularExpressions;
public class Record
{
public string Name { get; set; }
public string ID { get; set; }
public string Date { get; set; }
public string Job { get; set; }
}
public List<Record> Test()
{
string s = #"User name : John
ID : 221223
Date : 23.02.2018
Job: job1
User name : Andrew
ID : 378292
Date : 12.08.2017
Job: job2
User name : Chris
ID: 930712
Date : 05.11.2016
Job: job3
";
Regex r = new Regex(#"User\sname\s:\s(?<name>\w+).*?ID\s:\s(?<id>\w+).*?Date\s:\s(?<date>[0-9.]+).*?Job:\s(?<job>\w\w+)",RegexOptions.Singleline);
r.Matches(s);
return (from Match m in r.Matches(s)
select new Record
{
Name = m.Groups["name"].Value,
ID = m.Groups["id"].Value,
Date = m.Groups["date"].Value,
Job = m.Groups["job"].Value
}).ToList();
}
The CSV format seems to be what you're looking for (since you want to add some header to this file the actual CSV stars on 6th line):
random text 12234
another random text
User infos:
UserName;ID;Date;Job
John;221223;23.02.2018;job1
Andrew;378292;12.08.2017;job2
Chris;930712;05.11.2016;job3
And then you could read this file and parse it:
var lines = File.ReadAllLines("pathToFile");
var dataStartIndex = lines.IndexOf("UserName;ID;Date;Job");
var Users = lines.Skip(dataStartIndex + 1).Select(s =>
{
var splittedStr = s.Split(';');
return new User(splittedStr[0], splittedStr[1], splittedStr[2], splittedStr[3]);
}).ToList();
If you're working with console entry just skip the header part and let user enter comma separated values for each user on a different string. Parse it in a same way:
var splittedStr = ReadLine().Split(';');
var userToAdd = new User(splittedStr[0], splittedStr[1], splittedStr[2] , splittedStr[3]);
Users.Add(userToAdd);
i need to split a string in C# .net.
output i am getting : i:0#.f|membership|sdp950452#abctechnologies.com or i:0#.f|membership|tss954652#abctechnologies.com
I need to remove i:0#.f|membership| and #abctechnologies.com from the string. out put i need is sdp950452 or tss954652
also one more string I am getting is Pawar, Jaywardhan and i need it to be jaywardhan pawar
thanks,
Jay
Here is code example how you can do first part with Regex and the second with Splits and Replaces:
using System;
using System.Text.RegularExpressions;
namespace ConsoleApplication1
{
public class Program
{
public static void Main()
{
//First part
string first = "i:0#.f|membership|sdp950452#abctechnologies.com";
string second = "i:0#.f|membership|tss954652#abctechnologies.com";
string pattern = #"\|[A-Za-z0-9]+\#";
Regex reg = new Regex(pattern);
Match m1 = reg.Match(first);
Match m2 = reg.Match(second);
string result1 = m1.Value.Replace("|",string.Empty).Replace("#",string.Empty);
string result2 = m2.Value.Replace("|", string.Empty).Replace("#", string.Empty);
Console.WriteLine(result1);
Console.WriteLine(result2);
//Second part
string inputString = "Pawar, Jaywardhan";
string a = inputString.ToLower();
var b = a.Split(' ');
var result3 = b[1] + " " + b[0].Replace(",",string.Empty);
}
}
}
Using Linq to reduce the code lines
Link to dotnetfiddle code sample
using System.Linq;
using System;
public class Program
{
public static void Main()
{
//Extract email
string a = "i:0#.f|membership|sdp950452#abctechnologies.com";
string s = a.Split('|').Where(splitted => splitted.Contains("#")).FirstOrDefault().Split('#').First();
Console.WriteLine(s);
//Format Name
string name = "Pawar, Jaywardhan";
string formatted = String.Join(" ",name.Split(',').Reverse()).ToLower().TrimStart().TrimEnd();
Console.WriteLine(formatted);
}
}
I'm using c# MVC project.
I have a customer class and customer table.I have a Insert function with four parameter name , surname ,phone,address.I want to read .txt file line by line and split with "," and use this Insert function but I don't know how can create algorithm.
static void AddCustomer(string Name, string Surname, string Phone, string Address)
{
using (var session = NHibernateHelper.OpenSession())
{
using (var transaction = session.BeginTransaction())
{
var customer = new Customer
{
Name = Name,
Surname = Surname,
Phone = Phone,
Address = Address,
};
session.Save(customer);
transaction.Commit();
}
}
}
while ((line = file.ReadLine()) != null)
{
string text = file.ReadToEnd();
string[] lines = text.Split(',');
for (int i = 0; i < lines.Length; i++)
{
//HOW CAN I USER ADDCUSTOMER()
}
counter++;
}
You've almost got it. Assuming file is a StreamReader, you can just split the current line on comma, and pass the separate parts to the AddCustomer method:
while ((line = file.ReadLine()) != null)
{
// Split the line on comma
var lineParts = line.Split(',');
string name = lineParts[0];
string surname = lineParts[1];
string phone = lineParts[2];
string address = lineParts[3];
AddCustomer(name, surname, phone, address);
}
Please note that this does no error checking at all (lineParts[1] will blow up if there's no comma in the given line) and that this is a bad way to parse CSV (if the data contains comma's, which addresses tend to do, it'll not work properly). Use a CSV parsing library.
See Parsing CSV files in C#, with header and plenty of other questions about CSV, where it is suggested that you use the FileHelpers library. Your class that maps to and from the CSV file will look like this:
[DelimitedRecord(",")]
[IgnoreEmptyLines()]
public class MyProduct
{
[FieldOrder(0)]
public string Name { get; set; }
[FieldOrder(1)]
public string Surname { get; set; }
[FieldOrder(2)]
public string Phone { get; set; }
[FieldOrder(3)]
public string Address { get; set; }
}
And the code to read the file:
var engine = new FileHelperEngine<CustomerCsvRecord>();
CustomerCsvRecord[] customers = engine.ReadFile(fileName);
foreach (var customer in customers)
{
AddCustomer(customer.Name, customer.Surname, customer.Phone, customer.Address);
}
This will do your job.
string fileContent = System.IO.File.ReadAllText("YOUR_FILE_PATH");
//assumeing each customer record will be on separate line
string[] lines = fileContent.Split(new string [] {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries);
foreach (string line in lines)
{
//assuming a single line content will be like this "name,surname,phone,address"
string[] items = line.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
Customer cust = new Customer();
cust.Name = items[0];
cust.Surname = items[1];
cust.Phone = items[2];
cust.Address = items[3];
//now use this 'cust' object
}