Getting text element XML Node based on element name C# - c#

I want to create a function that will take an XML file and split it into its individual elements. Then depending on the element name I want to store the text from that element in an array. My function so far is:
public string[] read(string fileLoc)
{
//Create variables
r = XmlReader.Create(fileLoc, settingsR);
string[] content = new string[3];
while (r.Read())
{
if (r.NodeType == XmlNodeType.Element)
{
switch (r.Name)
{
case "Title":
content[0] = r.Name;
break;
case "Description":
content[1] = r.Name;
break;
default:
content[2] = r.Name;
break;
}
}
}
return content;
}
So far I can load the array with the name of the element, but not the text. Thanks

Related

How do I get all parameters and their value in Revit through C#?

public IList<Parameter> GetAllParameters(Reference reference, Document doc, IList<ElementId> elementIds)
{
Element element = SelectElement(doc, reference);
ParameterSet pSet = element.Parameters;
IList<Parameter> param = new List<Parameter>();
foreach (Parameter p in pSet)
{
if (p.Definition.Name.Equals(element.Name))
{
element.GetParameters(element.Name);
param.Add(p);
}
}
return param;
}
I am supposed to get all parameters from an element in Revit, although, this isn't just working. How can I fix this?
Basically, you already did it. You only need to get the parameter value. Something like this:
foreach (Parameter p in element.Parameters)
{
switch (p.StorageType)
{
case RvtDB.StorageType.Double:
double value = p.AsDouble();
break;
// ...
default:
string txt = p.AsValueString();
break;
}
}

Reading data from a text file into a struct with different data types c#

I have a text file that stores data about cars, its call car.txt. I want to read this text file and categorize each of the sections for each car. Ultimately I want to add this information into a doubly linked list. So far everything I have tried is either giving me format exception or out of range exception.
This is my public structure
public struct cars
{
public int id;
public string Make;
public string Model;
public double Year;
public double Mileage;
public double Price;
}
This is where I try reading the data into the struct then add it to the DLL
static void Main()
{
int Key;
cars item = new cars();
int preKey;
/* create an empty double linked list */
DoubleLinkedList DLL = new DoubleLinkedList();
string line;
StreamReader file = new StreamReader(#"C:\Users\Esther\Desktop\cars.txt");
while ((line = file.ReadLine()) != null)
{
Console.WriteLine(line);
var array = line.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None);
item.Make =array[0];
item.Model = array[1];
item.Year = Double.Parse(array[2]);
item.Mileage = Double.Parse(array[2]);
item.Price = Double.Parse(array[2]);
// Using newline to seprate each line of the file.
Console.WriteLine(line);
DLL.AppendToHead(item);
}
This is throws a format exception then an out of range exception. How do I get this code to read the text file into the struct and add it to my DLL? This is the car.txt file
BMW
228i
2008
122510
7800
Honda
Accord
2011
93200
9850
Toyota
Camry
2010
85300
9500
I've changed your double-linked list to a plain List<cars> for simplicity. You need to create a new cars item for each record, otherwise you'll end up with every element in your list referring to the same record (the last one processed). Each line has a different attribute of the car so you need to work out which attribute to save, using a counter (idx).
using System.Collections.Generic; // for List<cars>
... ... ...
public static void ReadMultiline()
{
// http://stackoverflow.com/questions/39945520/reading-data-from-a-text-file-into-a-struct-with-different-data-types-c-sharp
var DLL = new List<cars>();
string line;
StreamReader file = new StreamReader(#"cars.txt");
var item = new cars();
int idx = 0;
while ((line = file.ReadLine()) != null)
{
idx++;
switch ( idx ) {
case 1: item.Make = line; break;
case 2: item.Model = line; break;
case 3: item.Year = Double.Parse(line); break;
case 4: item.Mileage = Double.Parse(line); break;
case 5: item.Price = Double.Parse(line); break;
}
if (line == "" && idx > 0 )
{
DLL.Add(item);
idx = 0;
item = new cars(); // create new cars item
}
}
// pick up the last one if not saved
if (idx > 0 )
DLL.Add(item);
foreach( var x in DLL )
{
Console.WriteLine( String.Format( "Make={0} Model={1} Year={2} Mileage={3} Price={4}", x.Make, x.Model, x.Year, x.Mileage, x.Price) );
}
}
You are reading the file line by line with ReadLine, and trying to split a single line with a line ending. This will result in an array with just one element (E.G. "BMW")
You can either read the whole file and then split by lines or just assume that each line will contain some data.
The OutOfRangeException refers to your invocation of array[1] when the array contains only array[0] = "BMW".

How to read this part of the web XML file?

I am working on a XML reader which shows the result in the labels.
I want to read the node called "Opmerking" which is standing in "Opmerkingen"
A example:
<VertrekkendeTrein>
<RitNummer>4085</RitNummer>
<VertrekTijd>2014-06-13T22:00:00+0200</VertrekTijd>
<EindBestemming>Rotterdam Centraal</EindBestemming>
<TreinSoort>Sprinter</TreinSoort>
<RouteTekst>A'dam Sloterdijk, Amsterdam C., Duivendrecht</RouteTekst>
<Vervoerder>NS</Vervoerder>
<VertrekSpoor wijziging="false">4</VertrekSpoor>
<Opmerkingen>
<Opmerking> Rijdt vandaag niet</Opmerking>
</Opmerkingen>
</VertrekkendeTrein>
"Opmerkingen" is not always there, it is always changing. The code i use now:
XmlNodeList nodeList = xmlDoc.SelectNodes("ActueleVertrekTijden/VertrekkendeTrein/*");
and:
foreach (XmlNode nodelist2 in nodeList)
{
if (i < 17) //4
{
switch (nodelist2.Name)
{
case "VertrekTijd": string kuttijd4 = (nodelist2.InnerText);
var res4 = Regex.Match(kuttijd4, #"\d{1,2}:\d{1,2}").Value;
lblv4.Text = Convert.ToString(res4); break;
case "TreinSoort": lblts4.Text = (nodelist2.InnerText); break;
case "RouteTekst": lblvia4.Text = (nodelist2.InnerText); break;
case "VertrekSpoor": lbls4.Text = (nodelist2.InnerText); i++; break;
}
}
}
How can i read the part "Opmerking" and set it in a case?
I tried it a few times, but it failed.
i also tried:
case "Opmerking": var texeliseeneiland1 = (nodelist2.InnerText); if (texeliseeneiland1 == null) { } else { lblop1.Text = texeliseeneiland1; lblop1.Font = new Font(lblop1.Font.FontFamily, 17); lblop1.Visible = true; picop1.Visible = true; }; break;
Anyone who knows the answer?
Just extend your logic with check whether current node has child nodes and if so, read them and process:
if (nodelist2.HasChildNodes)
{
for (int i=0; i<nodelist2.ChildNodes.Count; i++)
{
var childNode = root.ChildNodes[i];
//do whatever you need to display the contents of the child node.
}
}
Also I have to recommend to consider LinqToXML or at least refactor the code you shared. With LinqToXML is might be as easy as this:
var temp = from remarkNode in nodelist2.Descendants("Opmerking")
select remarkNode.Value;
Somehow load the xml content in an XDocument object and loop through it.
Example: read it from a file
var doc = XDocument.Load("C:/test.xml");
foreach (var xe in doc.Descendants("Opmerking"))
{
var value = xe.Value;
//Do your job with value
}

c# string text, enum type

I am reading txt file, and I would like to separate it into some parts. This example of my TXT file:
"Part error(1) devic[3].data_type(2)"
"Escape error(3) device[10].data_type(12)"
I want to achieve such a situation that, when I have first word "Part" I would like to have enum type for it, and in switch I would like to call some function that will work with whole line, and on the other hand, when I will have first word "Escape", there will another case in switch that will call other functions. How can I do it? This is my code so far:
class Row
{
public enum Category { Part, Escape }
public string Error{ get; set; }
public string Data_Type { get; set; }
public string Device{ get; set; }
}
public object HandleRegex(string items)
{
Row sk = new Row();
Regex r = new Regex(#"[.]");
var newStr = r.Replace(items, #" ");
switch(this.category)
{
case Category.Part:
//I want to call here function HandlePart with my line as a parameter
HandlePart(newStr);
break;
case Category.Escape:
//Here I want to call Function HandleEscape for line with "Escape" word
HandleEscape(newStr);
break;
}
}
public object HandleRegex(string items)
{
Regex r = new Regex(#"[.]");
var newStr = r.Replace(items, #" ");
try {
category = (Category) new EnumConverter(typeof(Category)).ConvertFromString(items.Split(new string[]{" "},StringSplitOptions.RemoveEmptyEntries)[0]);
}
catch {
throw new ArgumentException("items doesn't contain valid prefix");
}
switch(category)
{
case Category.Part:
HandlePart(newStr);
break;
case Category.Escape:
HandleEscape(newStr);
break;
}
}
You could use TryParse :
Category outCategory;
Enum.TryParse(this.category, out outCategory)
switch(outCategory)
{
case Category.Part:
//I want to call here function HandlePart with my line as a parameter
HandlePart(newStr);
break;
case Category.Escape:
//Here I want to call Function HandleEscape for line with "Escape" word
HandleEscape(newStr);
break;
default:
// Needs to be handled
}
You can create Dictionary<Category, Action<string>> and then use it to call code according to category:
static void Main(string[] args)
{
var input = #"Part error(1) devic[3].data_type(2)
Escape error(3) device[10].data_type(12)";
var functions = new Dictionary<Category, Action<string>>()
{
{ Category.Part, HandlePart},
{ Category.Escape, HandleEscape }
};
foreach (var line in input.Split(new [] {Environment.NewLine }, StringSplitOptions.None))
{
Category category;
if(Enum.TryParse<Category>(line.Substring(0, line.IndexOf(' ')), out category) && functions.ContainsKey(category))
functions[category](line);
}
}
static void HandlePart(string line)
{
Console.WriteLine("Part handler call");
}
static void HandleEscape(string line)
{
Console.WriteLine("Escape handler call");
}
Output of program above:
Part handler call
Escape handler call
if you read the file line by line then you can do
string str = file.ReadLine();
string firstWord = str.substring(0, str.IndexOf(' ')).Trim().ToLower();
now you have your first word you can do
switch(firstWord){
case "escape":// your code
case "Part":// your code
}

Elegant way to save/load values into an array

I'm basically saving and loading values into an array to feed into a JSON library, and I'm just looking for a more elegant way to do this:
class properties to array
return new object[] { path, pathDir, name };
array to class properties
c.path = values[0];
c.pathDir = values[1];
c.name = values[2];
Simple solutions that ideally do not require additional run time overheads such as Reflection are appreciated.
Can I do something like this?
c.{path, pathDir, name} = values[0...2]
Edit: I'm specifically asking for arrays. I know about serialization and JSON and Protobuf and everything else everyone is suggesting.
Would this not do the trick?
return new {path= "/Some/Path", pathDir= "SiteRoot", name="MyPath"}
Edit:
//Mock function to simulate creating 5 objects with 'CreateArrayOb' function
public void CreatingObjects()
{
var lst = new List<object>();
for (var x = 0; x < 5; x++)
{
lst.Add(CreateArrayOb(new string[] {"Path" + x, "Dir" + x, "Path" + x}));
}
}
public object CreateArrayOb(object[] vals)
{
if (vals != null && vals.Any())
{
//Switch cases in the event that you would like to alter the object type returned
//based on the number of parameters sent
switch (vals.Count())
{
case 0:
break;
case 1:
break;
case 2:
break;
case 3:
return new { path = vals.ElementAt(0), pathDir = vals.ElementAt(1), name = vals.ElementAt(2) };
}
}
return null;
}

Categories