I am looking for the best way to compare XML data with a string.
the data is stored in a xml called test.xml, and must be compared with the name descendant, if there is a match more info from the xml must be added to a textbox and picture box.
My ( working ) code:
var xmlDocument = XDocument.Load("test.xml"); // XML koppellen
var key1 = xmlDocument.Descendants("NAME"); // XML filepath
var key2 = xmlDocument.Descendants("TITLE"); // XML titel
var key3 = xmlDocument.Descendants("BRAND"); // XML afbeelding
var key4 = xmlDocument.Descendants("TYPE"); // XML merk
var key5 = xmlDocument.Descendants("SOORT"); // XML type
var key6 = xmlDocument.Descendants("NAAM"); // XML naam
List<string> file = new List<string>();
List<string> title = new List<string>();
List<string> brand = new List<string>();
List<string> type = new List<string>();
List<string> soort = new List<string>();
List<string> naam = new List<string>();
int i = 0;
foreach (var key in key1)
{
file.Add(key.Value.Trim());
}
foreach (var key in key2)
{
title.Add(key.Value.Trim());
}
foreach (var key in key3)
{
brand.Add(key.Value.Trim());
}
foreach (var key in key4)
{
type.Add(key.Value.Trim());
}
foreach (var key in key5)
{
soort.Add(key.Value.Trim());
}
foreach (var key in key6)
{
naam.Add(key.Value.Trim());
}
foreach (var Name in naam)
{
if (textBox3.Text.ToString() == Name.ToString())
{
PDFLocation = file[i].ToString();
pictureBox1.Image = pdfhandler.GetPDFthumbNail(PDFLocation);
textBox4.Text =
title[i].ToString() + "\r\n" +
brand[i].ToString() + "\r\n" +
type[i].ToString() + "\r\n" +
soort[i].ToString() + "\r\n" +
textBox3.Text + "\r\n";
}
i++;
}
]
I think this is not the best way to do it, but cant see a better way....
Update: solution:
foreach (XElement element in xmlDocument.Descendants("PDFDATA"))
{
if (textBox3.Text.ToString() == element.Element("NAAM").Value.Trim())
{
PDFLocation = element.Element("NAME").Value.ToString();
pictureBox1.Image = pdfhandler.GetPDFthumbNail(PDFLocation);
textBox4.Text =
element.Element("TITLE").Value + "\r\n" +
element.Element("BRAND").Value + "\r\n";
break;
}
}
Instead of thinking of the xml and a bunch of individual lists of data, it helps to think of it more as objects. Then you can loop through each element one at a time and don't need to split it up into individual lists. This not only removes duplicate code but more importantly creates a better abstraction of the data you are working with. This makes it easier to read and understand what the code is doing.
foreach (XElement element in xmlDocument.Elements())
{
if (textBox3.Text.ToString() == element.Element("NAAM").Value)
{
PDFLocation = element.Element("NAAM").Value;
pictureBox1.Image = pdfhandler.GetPDFthumbNail(PDFLocation);
textBox4.Text =
element.Element("Title").Value + "\r\n" +
element.Element("Brand").Value + "\r\n" +
element.Element("Type").Value + "\r\n"
// access rest of properties...
}
}
Related
Using the example code works correctly to get the non-nested data from "issues", how can I get the nested data from "issues"? In the picture you can see which data we are talking about.
Code:
try
{
var dynObj = JsonConvert.DeserializeObject<dynamic>(strResponseValue);
string records = dynObj["issues"].ToString();
JArray a = JArray.Parse(records);
List<string> colNames = new List<string>() {"expand", "key", "id",
"self" };
string headerRow = "";
foreach (string colName in colNames)
{
headerRow += "\"" + colName + "\";";
}
headerRow = headerRow.TrimEnd(';');
headerRow += "\n";
string dataRows = "";
foreach (var record in a)
{
string thisRecord = "";
foreach (string colName in colNames)
{
thisRecord += "\"" + record[colName] + "\";";
}
thisRecord = thisRecord.TrimEnd(';');
thisRecord += "\n";
dataRows += thisRecord;
}
csvData = headerRow + dataRows;
Console.WriteLine("\ncsvData:");
Console.WriteLine(csvData);
}
catch (Exception ex)
{
Console.WriteLine("Exeption Error" + ex.ToString());
}
If the json is complex, you can let visual studio do the job.
Copy the json content
Use Edit/Paste Special - Paste JSON As Classes
Use the generated Class to deserialize your json content.
For instance deserialize to MyClass (from .Net Fundumentals - JSON Serialize/Deserialize):
MyClass? myclass = JsonSerializer.Deserialize<MyClass>(jsonString);
I am using Mailkit to send an email.
So in the body of the email, I am passing data like this:
message.Body = new TextPart("plain")
{
foreach (var item in model.Transaction)
{
Console.WriteLine(item.Account +"-"+item.Amount+"-"+item.Date);
}
Text = #"";
};
but I wanted to put item.Account, item.Amount, item.Date in #""
How can I do that?
you should use $
$"{item.Account}, {item.Amount}, {item.Date}";
Because # is used to escaping specials symbols
You won't be able to access item.* outside of foreach*.
To create a single string from multiple strings you could use string.Join:
List<string> l = new ();
foreach (var item in model.Transaction)
{
var fromSingleItem = $"{item.Account}-{item.Amount}-{item.Date}";
l.Append(fromSingleItem);
}
var fromAllItems = string.Join(", ", l);
* = What would time outside of foreach mean? Would it be the first item's data, or the last one's, or from the middle?
I would use a string builder for this
var sb= new StringBuilder();
foreach (var item in model.Transaction)
{
sb.Append( item.Account + "-" + item.Amount.ToString() + "-"
+ item.Date.ToString() + "\n");
}
message.Body = new TextPart("plain")
{
Text = sb.ToString();
};
or if you have only several items
var sb= string.Empty;
foreach (var item in model.Transaction)
{
sb+= item.Account + "-" + item.Amount.ToString() + "-" + item.Date.ToString() + "\n");
}
Serge has the right idea, but I would tweak it a bit as there is a performance penalty every time you concatenate using the '+' symbol (a new String object is instantiated when you concatenate with '+'). I would suggest you continue to use StringBuilder even if you only have a single item in your foreach loop.
var builder = new StringBuilder();
foreach (var item in model.Transaction)
{
builder.Append(item.Account);
builder.Append("-");
builder.Append(item.Amount);
builder.Append("-");
builder.AppendLine(item.Date);
}
message.Body = new TextPart("plain")
{
Text = builder.ToString()
};
Inside a foreach loop, i am counting and getting the full path of files with similar names, and I need to access them later so I want to make a list that saves them, and my question is how can I do this?
I´ve been trying to do it like this.
protected void ShowPng(string pathPgnImg)
{
btnNextPage.Visible = true;
string sImageName = "";
string sImagePathImages = Server.MapPath("Anexos/");
string pngFile = "";
List<string> pngs = new List<string> { pngFile };
string FileWithoutPath = Path.GetFileName(pathPgnImg);
string fileWithoutPathAndExt = Path.GetFileNameWithoutExtension(FileWithoutPath);
if(fileWithoutPathAndExt + "_pag" + LblHiddenImagePageNumber != fileWithoutPathAndExt + "_pag" + "" )
{
DirectoryInfo AnexoDirectory = new DirectoryInfo(PathForPdf);
FileInfo[] filesInDir = AnexoDirectory.GetFiles(fileWithoutPathAndExt + "_pag" + "*.png");
foreach (FileInfo foundFile in filesInDir)
{
pngFile = foundFile.FullName;
pngs = new List<string> { pngFile };
}
string sFileExt = Path.GetExtension(pngFile);
pngFile = Path.GetFileNameWithoutExtension(pngFile);
m_sImageNameUserUpload = pngFile + sFileExt;
m_sImageNameGenerated = Path.Combine(sImagePathImages, m_sImageNameUserUpload);
//Literal1.Text += "<img src=" + '"' + pngFile + '"' + "/>";
imgCrop.ImageUrl = "Anexos\\" + Path.GetFileName(pngFile);
if (m_sImageNameUserUpload != "")
{
pnlCrop.Visible = true;
imgCrop.ImageUrl = "Anexos/" + m_sImageNameUserUpload;
Session["ImageName"] = m_sImageNameUserUpload;
}
}
}
You can find what I mean in these lines here:
foreach (FileInfo foundFile in filesInDir)
{
pngFile = foundFile.FullName;
pngs = new List<string> { pngFile };
}
So what can I do? the output right now for it is although it adds the value it doesn't save it and add the other ones just adds that one to the list.
Thank you #Knoop for the answer to this simple question.
Turns out the only problem i was having was i wasn´t adding up to the list count.
So start by making a list:
List<string> Files = new List<string>;
Since i was trying to add the value of a variable that kept updating trough a foreach loop, ill use that example:
foreach (FileInfo foundFile in filesInDir)
{
pngFile = foundFile.FullName;
pngs.Add(pngFile);
}
Just to explain what i changed from the original question post to this answer was this line:
pngs.Add(pngFile);
with the name of the list and the .ADD it keeps adding the pngFile value everytime the loop restarts.
Once again thank you to #Knoop for the help.
I hope this helps some of you too.
I need to see if any phrase, such as "duckbilled platypus" appears in a string array.
In the case I'm testing, the phrase does exist in the string list, as shown here:
Yet, when I look for that phrase, as shown here:
...it fails to find it. I never get past the "if (found)" gauntlet in the code below.
Here is the code that I'm using to try to traverse through the contents of one doc to see if any phrase (two words or more) are found in both documents:
private void FindAndStorePhrasesFoundInBothDocs()
{
string[] doc1StrArray;
string[] doc2StrArray;
slPhrasesFoundInBothDocs = new List<string>();
slAllDoc1Words = new List<string>();
int iCountOfWordsInDoc1 = 0;
int iSearchStartIndex = 0;
int iSearchEndIndex = 1;
string sDoc1PhraseToSearchForInDoc2;
string sFoundPhrase;
bool found;
int iLastWordIndexReached = iSearchEndIndex;
try
{
doc1StrArray = File.ReadAllLines(sDoc1Path, Encoding.UTF8);
doc2StrArray = File.ReadAllLines(sDoc2Path, Encoding.UTF8);
foreach (string line in doc1StrArray)
{
string[] subLines = line.Split();
foreach (string whirred in subLines)
{
if (String.IsNullOrEmpty(whirred)) continue;
slAllDoc1Words.Add(whirred);
}
}
iCountOfWordsInDoc1 = slAllDoc1Words.Count();
sDoc1PhraseToSearchForInDoc2 = slAllDoc1Words[iSearchStartIndex] + ' ' + slAllDoc1Words[iSearchEndIndex];
while (iLastWordIndexReached < iCountOfWordsInDoc1 - 1)
{
sFoundPhrase = string.Empty;
// Search for the phrase from doc1 in doc2;
found = doc2StrArray.Contains(sDoc1PhraseToSearchForInDoc2);
if (found)
{
sFoundPhrase = sDoc1PhraseToSearchForInDoc2;
iSearchEndIndex++;
sDoc1PhraseToSearchForInDoc2 = sDoc1PhraseToSearchForInDoc2 + ' ' + slAllDoc1Words[iSearchEndIndex];
}
else //if not found, inc vals of BOTH int args and, if sFoundPhrase not null, assign to sDoc1PhraseToSearchForInDoc2 again.
{
iSearchStartIndex = iSearchEndIndex;
iSearchEndIndex = iSearchStartIndex + 1;
if (!string.IsNullOrWhiteSpace(sFoundPhrase)) // add the previous found phrase if there was one
{
slPhrasesFoundInBothDocs.Add(sFoundPhrase);
}
sDoc1PhraseToSearchForInDoc2 = slAllDoc1Words[iSearchStartIndex] + ' ' + slAllDoc1Words[iSearchEndIndex];
} // if/else
iLastWordIndexReached = iSearchEndIndex;
} // while
} // try
catch (Exception ex)
{
MessageBox.Show("FindAndStorePhrasesFoundInBothDocs(); iSearchStartIndex = " + iSearchStartIndex.ToString() + "iSearchEndIndex = " + iSearchEndIndex.ToString() + " iLastWordIndexReached = " + iLastWordIndexReached.ToString() + " " + ex.Message);
}
}
doc2StrArray does contain the phrase sought, so why does doc2StrArray.Contains(sDoc1PhraseToSearchForInDoc2) fail?
This should do what you want:
found = Array.FindAll(doc2StrArray, s => s.Contains(sDoc1PhraseToSearchForInDoc2));
In List<T>, Contains() looking for an T, Here in your code to found be true must have all the text in particular index (NOT part of it).
Try this
var _list = doc2StrArray.ToList();
var found = _list.FirstOrDefault( w => w.Contains( sDoc1PhraseToSearchForInDoc2 ) ) != null;
i'm reading a file with 10002 lines, in each line there is a name that I want to compare with a single string, and if this string is the same, i want to add the string file to a listbox, I'm using the FILE.READLINE and then add each line to a list then I use .CONTAINS method and doesnt works also with == but that doesn work either...Any suggestions?
//This is my code:
foreach (string h in Directory.EnumerateFiles(NomDirec, "resume*"))
{
this.listBox1.Items.Add(h);
//Read Lines here and add them to a list and a listbox
var NombreLinea = File.ReadLines(h);
foreach (var item in NombreLinea)
{
NombreAbuscar.Add(item).Remove(item.IndexOf(":"));
this.listBox3.Items.Add(item);
}
//Here I want to add this file only if "NombreCompleto" is present in my resume file.
foreach (string t in Directory.EnumerateFiles(NomDirec, "ESSD1*"))
{
string[] Nombre = File.ReadLines(t).ElementAtOrDefault(6).Split(':');
string[] ApellidoPat = File.ReadLines(t).ElementAtOrDefault(7).Split(':');
string[] ApellidoMat = File.ReadLines(t).ElementAtOrDefault(8).Split(':');
string NombreCompleto = ApellidoPat[1] + ApellidoMat[1] + "," + " " + Nombre[1] + " " + ":";
foreach (var item in NombreAbuscar)
{
if (NombreCompleto == item)
{
this.listBox1.Items.Add(t);
break;
}
}
}
Could be a way to only read the a certain part of the line and add it to my listbox??