I have an xml file, and I need to be able to sort it in either a list or an array
The XML:
<Restaurant>
<name>test</name>
<location>test</location>
</Restaurant>
<Restaurant>
<name>test2</name>
<location>test2</location>
</Restaurant>
All the Restaurants will have the same number of fields and the same names for the fields, but the number of <Restaurant></Restaurant> in a given xml file is unknown.
In other words, I need an array or list and be able to do this:
String name = restaurantArray[0].name;
String location = restaurantArray[0].location;
While I don't need that syntax obviously, this is the functionality I'm trying to accomplish.
If you are trying to get names of restaurants and Restaurant elements are direct child of root element:
string[] names = xdoc.Root.Elements("Restaurant")
.Select(r => (string)r.Element("name"))
.ToArray();
EDIT: If you are trying to parse whole restaurant objects:
var restaurants = from r in xdoc.Root.Elements("Restaurant")
select new {
Name = (string)r.Element("name"),
Location = (string)r.Element("location")
};
Usage:
foreach(var restaurant in restaurants)
{
// use restaurant.Name or restaurant.Location
}
You can create instance of some Restaurant class instead of anonymous object here. Also you can put restaurants to array by simple restaurants.ToArray() call.
The answer by Sergey is very clear but if you want to load it from the saved file I think it will be helpful for you.
Actually for loading a XML files to the array I used this method, But my array was double Jagged array. The code that I used is below I modified based on your resturant:
private static resturant[][] LoadXML(string filePath)
{
//Open the XML file
System.IO.FileStream fs = new System.IO.FileStream(filePath, System.IO.FileMode.Open);
// First create a xml Serializer object
System.Xml.Serialization.XmlSerializer xmlSer = new System.Xml.Serialization.XmlSerializer(typeof(resturant[][]));
resturant[][] resturant = (resturant[][])xmlSer.Deserialize(fs);
// Close the file stream
fs.Close();
return resturant ;
}
By this function you can read all your data as below :
double [][] res = LoadXML(#"YOUR FILE PATH");
As you know the first and second element of each resturant is name and location I think accessing to them is now easy for you.
Related
I have a lot of JSON format data into text file and format is like:
[{"ev":"AM","sym":"TMHC","v":1000,"av":74917,"op":18.92,"vw":19.1305,"o":19.13,"c":19.15,"h":19.15,"l":19.13,"a":19.143,"z":90,"n":1,"s":1549380300000,"e":1549380360000},{"ev":"AM","sym":"SPYG","v":7103,"av":184266,"op":35.27,"vw":35.3148,"o":35.3264,"c":35.34,"h":35.34,"l":35.3258,"a":35.3345,"z":710,"n":1,"s":1549380300000,"e":1549380360000},
{"ev":"AM","sym":"AAPL","v":73,"av":1866,"op":35.27,"vw":35.3148,"o":35.3264,"c":35.34,"h":35.34,"l":35.3258,"a":35.3345,"z":710,"n":1,"s":1549380300000,"e":1549380360000}]
So I need to find json element of particular symbol. Like if I use AAPL then it gives us all AAPL element data from txt file. Like
{"ev":"AM","sym":"AAPL","v":73,"av":1866,"op":35.27,"vw":35.3148,"o":35.3264,"c":35.34,"h":35.34,"l":35.3258,"a":35.3345,"z":710,"n":1,"s":1549380300000,"e":1549380360000}
So please can you help me to how should I make it ?
static void xPathUsing()
{
const string filePath = #"D:\Aggregate_Minute_AAPL.txt";
using (StreamReader r = new StreamReader(filePath))
{
string json = r.ReadToEnd();
}
}
As you need to run multiple operations on the data, the best way would be to read the data into memory once (or again whenever the data changes) and hold them in a way that supports fast querying. In order to find a row by the symbol, you could create a dictionary that holds the data.
The following samples use the widely used JSON.NET library for parsing the JSON.
First, you need to define a class that ressembles the schema of your JSON objects, e.g.:
class Row
{
[JsonProperty("sym")]
public string Symbol { get; set; }
public decimal vw { get; set; }
// ...
}
Please note that you can use the JsonProperty attribute in order to be able to assign different names to the properties of the class than in the JSON.
The following sample shows how to read the data from a file and how to convert it to a dictionary:
var input = File.ReadAllText("C:\\Temp\\abc.json");
var rows = JsonConvert.DeserializeObject<IEnumerable<Row>>(input);
var dict = rows.ToDictionary(x => x.Symbol, x => x, StringComparer.OrdinalIgnoreCase);
After preparing your dictionary once, you can get the corresponding row by using the indexer:
var aaplRow = dict["AAPL"];
I had written a list object to a file like this
private List<string> _cacheFileList=new List<string>(4);
_cacheFileList.Add("Something");
using (StreamWriter file = new StreamWriter(#"cache.bin"))
{
file.Write(_cacheFileList);
}
Now how could I retrieve whole list object??
Instead of using StreamWriter like that, use BinaryFormatter to serialize your list. Then you can easily retrieve your list back by deserializing. MSDN has a good example about how to do that.
If you just want a text file with a single line per list entry, you could try the code below. Of course, you would need error handling and need to ensure that the strings in the list did not contain newlines.
// Write
List<string> _listA = new List<string>(4);
_listA.Add("Test");
_listA.Add("Test2");
_listA.Add("Test3");
_listA.Add("Test4");
System.IO.File.WriteAllLines("test.txt", _listA);
// Read
List<string> _listB = new List<string>(4);
_listB.AddRange(System.IO.File.ReadAllLines("test.txt"));
If you want just write your list line by line then you can modify your code like this:
var cacheFileList = new List<string>(4);
cacheFileList.Add("Something");
using (var file = new StreamWriter(#"cache.bin"))
{
file.Write(string.Join("\r\n", cacheFileList));
}
Beginner programmer here so please keep (explanation of) answers as simple as possible.
For an assignment we got a text file that contains a large amount of lines.
Each line is a different 'Order' with an ordernumber, location, frequency (amount of times per week), and a few other arguments.
Example:
18; New York; 3PWK; ***; ***; etc
I've made it so that each line is read and stored in a string with
string[] orders = System.IO.File.ReadAllLines(#<filepath here>);
And I've made a separate class called "Order" which has a get+set for all the properties like ordernumber, etc.
Now I'm stuck on how to actually get the values in there. I know how string splitting works but not how I can make unique objects in a loop.
I'd need something that created a new Order for every line and then assign Order.ordernumber, Order.location etc.
Any help would be MUCH appreciated!
An easy approach will be to make a class to define the orders like this:
public class Order{
public string OrderNumber{get;set;}
public string OrderId{get;set;}
public string OrderSomeThingElse{get;set;}
}
Then initialize a List:
var orderList = new List<Order>();
Then loop through and populate it:
foreach( var order in orders ){
var splitString = order.Split(';');
orderList.Add( new Order{
OrderNumber = splitString[0],
OrderId = splitString[1],
OrderSomeThingElse = splitString[2]
});
}
If you want an easy, but not that elegant approach, this is it.
In addition to all the good answers you've already received. I recommend you to use File.ReadLines() instead File.ReadAllLines() Because you are reading large file.
The ReadLines and ReadAllLines methods differ as follows: When you use ReadLines, you can start enumerating the collection of strings before the whole collection is returned; when you use ReadAllLines, you must wait for the whole array of strings be returned before you can access the array. Therefore, when you are working with very large files, ReadLines can be more efficient. MSDN
Unless I misunderstand... do you mean something like this?
var ordersCollection = new List<Order>();
foreach (var order in orders)
{
var o = new Order();
o.PropertyName = ""; // Assign your property values like this
ordersCollection.Add(o);
}
// ordersCollection is now full of your orders.
I have built a REST API returning JSON for one part of my application... Here it returns a list of vehicles with the vehicles specs. There is a list of "Features" which are bool fields on each vehicle. What im trying to achieve in the XML feed I provide in another part of the solution, is to only display the features that are present and NOT to display the ones that return false.
My XML is formed by the following code:
var rawApiResponse = GetRawApiResponse(URLForAPI);
//Convert the JSON returned result to XML
var xmlDocument = JsonConvert.DeserializeXmlNode(rawApiResponse, "DealersStock");
var sw = new StringWriter();
var xw = new XmlTextWriter(sw);
xmlDocument.WriteTo(xw);
return Content(sw.ToString(), "text/xml");
I was wondering what the best way to remove the unwanted returned values in XML?
I was thinking along the lines of write to string and use
string.Replace("<Feature1>false</Feature1>", "")
or is there a better way of handling the XML at this point?
Or should I be doing this at the API level of the application?
Many thanks
I would suggest to do it where you retrieve the data. Something like
v.Features.Where(f => f)
edit:
Given a IEnumerable< Vehicle > x, you can enumerate it and select just the "true" features
foreach (var v in x)
v.Features = v.Features.Where(f => f);
(you can create a new IEnumerable if you don't want to change de data in the original collection for some reason)
I have an XML file, I have a node and I read all ChildNodes. The name of the childNode match to a variable I have to set with the value of this childNode.
In the loop, I'd like set :
myvar1 to MyValue1
myvar2 to MyValue2
The C# Code :
protected string myvar1;
protected string myvar2;
The XML content look like this :
<parameters>
<myvar1>MyValue1</myvar1>
<myvar2>MyValue2</myvar2>
</parameters>
C# set variables :
foreach (var item in xmlParamInstallation.SelectNodes("parameters")[0].ChildNodes)
{
??????
}
Any idea ?
Thanks,
UPDATE 1:
the value "field" in the loop is null all the time.
public class ParametersTest
{
public string myvar1 { get; set; }
public string myvar2 {get; set;}
}
var type = typeof(ParametersTest);
foreach (XmlNode item in xmlParamInstallation.SelectNodes("parameters")[0].ChildNodes)
{
var field = type.GetField(item.LocalName);
field.SetValue(field, item.InnerText);
}
You can do it using Reflection:
var type = typeof(SomeClass);
var field = type.GetField(item.Name);
field.SetValue(null, item.InnerText);
RE: UPDATE 1
var parameters = new ParametersTest();
var type = parameters.GetType();
var s = #"<parameters>
<MyVar1>MyValue1</MyVar1>
<MyVar2>MyValue2</MyVar2>
</parameters>";
var xmlParamInstallation = new XmlDocument();
xmlParamInstallation.LoadXml(s);
foreach (XmlNode item in xmlParamInstallation.SelectNodes("parameters")[0].ChildNodes)
{
var field = type.GetProperty(item.LocalName);
field.SetValue(parameters, item.InnerText, null);
}
If you are seeking to assign variables based on the names of nodes in XML, you have at least a couple options:
Deserialize the XML structure into an object with corresponding member names
Populate the variables using reflection
Populate the variables using dynamic method calls/expression trees that know how to read the contents of the XML node into an object property.
All of these approaches suggest a more object-oriented approach to the problem then just populating a few variables, but it would be easy to create a lightweight structure with the appropriate members which is populated by reading the XML document.
You could also use a key-based collection (like a Dictionary<string, string>) to store the values if you are just looking to build a simple name/value collection from the source XML.
If you put the names and values in a dictionary, you can easily get the values by name:
Dictionary<string, string> parameters =
xmlParamInstallation.SelectNodes("parameters")[0].ChildNodes
.ToDictionary(n => n.Name, n => n.InnerText);
myvar1 = parameters["myvar1"];
myvar2 = parameters["myvar2"];
You could either do as "Default" said, or you could look into Reflection. By using the Type.GetMember(string) method you could find a member with the given name (the tag name in your XML) and set its value.
EDIT
Samich beat me, so I'll give him +1 - he's got sample code as well.
You can check out the XmlSerializer class