I want to get data from a XML file (https://xml.buienradar.nl/) and fill a combobox with that data. I want each regio from <weerstation regio=>
to be shown in the combobox.
I could not find anything working for me in UWP
Easiest way is to use XElement to load XML and then query over it.
First you need ComboBox in XAML page:
<ComboBox x:Name="Stations" />
Add new event handler for Loaded event and in code behind use this code to load XML and fill ComboBox:
private void MainPage_OnLoaded(object sender, RoutedEventArgs e)
{
var requestUri = new Uri("https://xml.buienradar.nl/");
var httpClient = new HttpClient();
var httpResponse = await httpClient.GetAsync(requestUri);
httpResponse.EnsureSuccessStatusCode();
var httpResponseStream = await httpResponse.Content.ReadAsStreamAsync();
var root = XElement.Load(httpResponseStream);
var stations =
from element in root.Descendants("weerstation")
select element;
foreach (var station in stations)
{
Stations.Items?.Add(station.Attribute("id")?.Value);
}
}
Here is link to source where I get idea.
And also link where you'll find documentation how to do simple HTTP GET request.
You could use LinqToXML to read the data and then set that as the ItemSource.
You can start of with the following snippet (see in action here):
var xml = XDocument.Load("https://xml.buienradar.nl/");
var weerstationList = xml.Descendants("weerstation");
var weerstations = weerstationList.Select(w => new Item()
{
Id = w.Attribute("id").Value,
Name = w.Descendants("stationnaam").First().Value
});
and the following helper class:
public class Item
{
public string Id { get; set; }
public string Name { get; set; }
}
You can then set the list of items weerstations as your ItemSource of the combo-box.
Related
I'm trying to get information from that page : http://www.wowhead.com/transmog-sets?filter=3;5;0#transmog-sets
rows look like this when inspecting elements :
I've tried this code but it return me null every time on any nodes:
public class ItemSetsTransmog
{
public string ItemSetName { get; set; }
public string ItemSetId { get; set; }
}
public partial class Fmain : Form
{
DataTable Table;
HtmlWeb web = new HtmlWeb();
public Fmain()
{
InitializeComponent();
initializeItemSetTransmogTable();
}
private async void Fmain_Load(object sender, EventArgs e)
{
int PageNum = 0;
var itemsets = await ItemSetTransmogFromPage(0);
while (itemsets.Count > 0)
{
foreach (var itemset in itemsets)
Table.Rows.Add(itemset.ItemSetName, itemset.ItemSetId);
itemsets = await ItemSetTransmogFromPage(PageNum++);
}
}
private async Task<List<ItemSetsTransmog>> ItemSetTransmogFromPage(int PageNum)
{
String url = "http://www.wowhead.com/transmog-sets?filter=3;5;0#transmog-sets";
if (PageNum != 0)
url = "http://www.wowhead.com/transmog-sets?filter=3;5;0#transmog-sets:75+" + PageNum.ToString();
var doc = await Task.Factory.StartNew(() => web.Load(url));
var NameNodes = doc.DocumentNode.SelectNodes("//*[#id=\"tab - transmog - sets\"]//div//table//tr//td//div//a");
var IdNodes = doc.DocumentNode.SelectNodes("//*[#id=\"tab - transmog - sets\"]//div//table//tr//td//div//a");
// if these are null it means the name/score nodes couldn't be found on the html page
if (NameNodes == null || IdNodes == null)
return new List<ItemSetsTransmog>();
var ItemSetNames = NameNodes.Select(node => node.InnerText);
var ItemSetIds = IdNodes.Select(node => node.InnerText);
return ItemSetNames.Zip(ItemSetIds, (name, id) => new ItemSetsTransmog() { ItemSetName = name, ItemSetId = id }).ToList();
}
private void initializeItemSetTransmogTable()
{
Table = new DataTable("ItemSetTransmogTable");
Table.Columns.Add("ItemSetName", typeof(string));
Table.Columns.Add("ItemSetId", typeof(string));
ItemSetTransmogDataView.DataSource = Table;
}
}
}
why does my script doesn't load any of theses nodes ? how can i fix it ?
Your code does not load these nodes because they do not exist in the HTML that is pulled back by HTML Agility Pack. This is probably because a large majority of the markup you have shown is generated by JavaScript. Just try inspecting the doc.ParsedText property in your ItemSetTransmogFromPage() method.
Html Agility Pack is an HTTP Client/Parser, it will not run scripts. If you really need to get the data using this process then you will need to use a "headless browser" such as Optimus to retrieve the page (caveat: I have not used this library, though a nuget package appears to exist) and then probably use HTML Agility Pack to parse/query the markup.
The other alternative might be to try to parse the JSON that exists on this page (if this provides you with the data that you need, although this appears unlikely).
Small note - I think the id in you xpath should be "tab-transmog-sets" instead of "tab - transmog - sets"
In my ElasticSearch server, I have an existing index template, which contains some settings and some mappings.
I want to add a mapping for a new type to the template, but since it's not possible to update templates, I need to delete the existing one and recreate it.
Since I would like to keep all the existing settings, I tried getting the existing definition, add the mapping to it and then delete/recreate, like in this example:
using Nest;
using System;
public class SomeNewType {
[ElasticProperty(Index = FieldIndexOption.NotAnalyzed)]
public string SomeField { get; set; }
[ElasticProperty(Index = FieldIndexOption.Analyzed)]
public string AnotherField { get; set; }
}
class Program {
static void Main(string[] args) {
var settings = new ConnectionSettings(uri: new Uri("http://localhost:9200/"));
var client = new ElasticClient(settings);
var templateResponse = client.GetTemplate("sometemplate");
var template = templateResponse.TemplateMapping;
client.DeleteTemplate("sometemplate");
// Add a mapping to the template somehow...
template.Mappings.Add( ... );
var putTemplateRequest = new PutTemplateRequest("sometemplate") {
TemplateMapping = template
};
client.PutTemplate(putTemplateRequest);
}
}
However, I cannot find a way to add a mapping to the template definition using the ElasticProperty attributes, like in
client.Map<SomeNewType>(m => m.MapFromAttributes());
Is it possible to create a RootObjectMapping to add to the Mappings collection with something similar to MapFromAttributes?
You can do this by using the more robust PutMappingDescriptor to get a new RootObjectMapping, then add that into the collection returned by your GET _template request, like so:
var settings = new ConnectionSettings(uri: new Uri("http://localhost:9200/"));
var client = new ElasticClient(settings);
var templateResponse = client.GetTemplate("sometemplate");
var template = templateResponse.TemplateMapping;
// Don't delete, this way other settings will stay intact and the PUT will override ONLY the mappings.
// client.DeleteTemplate("sometemplate");
// Add a mapping to the template like this...
PutMappingDescriptor<SomeNewType> mapper = new PutMappingDescriptor<SomeNewType>(settings);
mapper.MapFromAttributes();
RootObjectMapping newmap = ((IPutMappingRequest) mapper).Mapping;
TypeNameResolver r = new TypeNameResolver(settings);
string mappingName = r.GetTypeNameFor(typeof(SomeNewType));
template.Mappings.Add(mappingName, newmap);
var putTemplateRequest = new PutTemplateRequest("sometemplate")
{
TemplateMapping = template
};
var result = client.PutTemplate(putTemplateRequest);
Note: TypeNameResolver is in the Nest.Resolvers namespace
As noted in the comment above, I recommend that you NOT delete the old template if the mappings are the only thing that needs updated, otherwise you will need to copy all of the other relevant settings into your new request.
Hello i need your super help.
Im not soo skilled in C# and i stack for about 6 hours on this. So please if anyone know help me . Thx
I have Xml like this
<COREBASE>
<AGENT>
<AGENT_INDEX>1</AGENT_INDEX>
<AGENT_PORTER_INDEX>
</AGENT_PORTER_INDEX>
<AGENT_NAME>John</AGENT_NAME>
<AGENT_SURNAME>Smith</AGENT_SURNAME>
<AGENT_MOBILE_NUMBER>777777777</AGENT_MOBILE_NUMBER>
</AGENT>
<AGENT>
<AGENT_INDEX>2</AGENT_INDEX>
<AGENT_PORTER_INDEX>1
</AGENT_PORTER_INDEX>
<AGENT_NAME>Charles</AGENT_NAME>
<AGENT_SURNAME>Bukowski</AGENT_SURNAME>
<AGENT_MOBILE_NUMBER>99999999</AGENT_MOBILE_NUMBER>
</AGENT>
</COREBASE>
And I need to select agent by index in windows forms combo box and than edit and save his attributes to xml. I found how to edit and save it but i dont know why but its saved to the first agent and overwrite his attributes in XML but not in the selected one.. :-(
Plese i will be glad for any help
private void buttonEditAgent_Click(object sender, EventArgs e)
{
XmlDocument AgentBaseEdit = new XmlDocument();
AgentBaseEdit.Load("AgentBase.xml");
XDocument AgentBase = XDocument.Load("AgentBase.xml");
var all = from a in AgentBase.Descendants("AGENT")
select new
{
agentI = a.Element("AGENT_INDEX").Value,
porterI = a.Element("AGENT_PORTER_INDEX").Value,
agentN = a.Element("AGENT_NAME").Value,
agentS = a.Element("AGENT_SURNAME").Value,
agentM = a.Element("AGENT_MOBILE_NUMBER").Value,
};
foreach (var a in all)
{
if ("" == textBoxEditAgentIndex.Text.ToString())
{
MessageBox.Show("You must fill Agent Index field !!", "WARNING");
}
else
{
// AgentBaseEdit.SelectSingleNode("COREBASE/AGENT/AGENT_INDEX").InnerText == textBoxEditAgentIndex.Text
if (a.agentI == textBoxEditAgentIndex.Text.ToString())
{
AgentBaseEdit.SelectSingleNode("COREBASE/AGENT/AGENT_INDEX").InnerText = textBoxEditAgentIndex.Text;
AgentBaseEdit.SelectSingleNode("COREBASE/AGENT/AGENT_PORTER_INDEX").InnerText = textBoxEditAgentPorterIndex.Text;
AgentBaseEdit.SelectSingleNode("COREBASE/AGENT/AGENT_NAME").InnerText = textBoxEditAgentName.Text;
AgentBaseEdit.SelectSingleNode("COREBASE/AGENT/AGENT_SURNAME").InnerText = textBoxEditAgentSurname.Text;
AgentBaseEdit.SelectSingleNode("COREBASE/AGENT/AGENT_MOBILE_NUMBER").InnerText = textBoxEditAgentMobile.Text;
AgentBaseEdit.Save("AgentBase.xml");
ClearEditAgentTxtBoxes();
}
}
}
}
Am i on the right way but i dont see the doors or i am totaly wrong ? Thx all. Miko
OK i tried it this way but it didnt changed the inner text
string agentIndex = comboBoxEditAgentI.SelectedItem.ToString();
XmlDocument AgentBaseEdit = new XmlDocument();
AgentBaseEdit.Load("AgentBase.xml");
XDocument AgentBase = XDocument.Load("AgentBase.xml");
var xElemAgent = AgentBase.Descendants("AGENT")
.First(a => a.Element("AGENT_INDEX").Value == agentIndex);
xElemAgent.Element("AGENT_MOBILE_NUMBER").Value = textBoxEditAgentMobile.Text;
xElemAgent.Element("AGENT_SURNAME").Value = textBoxEditAgentSurname.Text;
AgentBaseEdit.Save("AgentBase.xml");
It would be easier if you use Linq2Xml.
int agentIndex = 2;
XDocument xDoc = XDocument.Load(filename);
var xElemAgent = xDoc.Descendants("AGENT")
.First(a => a.Element("AGENT_INDEX").Value == agentIndex.ToString());
//or
//var xElemAgent = xDoc.XPathSelectElement(String.Format("//AGENT[AGENT_INDEX='{0}']",agentIndex));
xElemAgent.Element("AGENT_MOBILE_NUMBER").Value = "5555555";
xDoc.Save(fileName)
PS: namespaces: System.Xml.XPath System.Xml.Linq
It does not work, because you are selecting the first agent explicitly with in each loop
AgentBaseEdit.SelectSingleNode("COREBASE/AGENT/...")
But you can do it easier by reading and changing withing the same xml document. I'm only changing the agent name and replacing it with "test 1", "test 2", ...
XDocument AgentBase = XDocument.Load("AgentBase.xml");
int i = 0;
foreach (XElement el in AgentBase.Descendants("AGENT")) {
el.Element("AGENT_NAME").Value = "test " + ++i;
// ...
}
AgentBase.Save("AgentBase.xml");
UPDATE
However, I'm suggesting you to separate the logic involving the XML handling from the form. Start by creating an Agent class
public class Agent
{
public string Index { get; set; }
public string PorterIndex { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public string Mobile { get; set; }
}
Then create an interface defining the needed functionality for an agent repository. The advantage of this interface is that it will make it easier later to switch to another kind of repository like a relational database.
public interface IAgentRepository
{
IList<Agent> LoadAgents();
void Save(IEnumerable<Agent> agents);
}
Then create a class that handles the agents. Here is a suggestion:
public class AgentXmlRepository : IAgentRepository
{
private string _xmlAgentsFile;
public AgentXmlRepository(string xmlAgentsFile)
{
_xmlAgentsFile = xmlAgentsFile;
}
public IList<Agent> LoadAgents()
{
XDocument AgentBase = XDocument.Load(_xmlAgentsFile);
var agents = new List<Agent>();
foreach (XElement el in AgentBase.Descendants("AGENT")) {
var agent = new Agent {
Index = el.Element("AGENT_INDEX").Value,
PorterIndex = el.Element("AGENT_PORTER_INDEX").Value,
Name = el.Element("AGENT_NAME").Value,
Surname = el.Element("AGENT_SURNAME").Value,
Mobile = el.Element("AGENT_MOBILE_NUMBER").Value
};
agents.Add(agent);
}
return agents;
}
public void Save(IEnumerable<Agent> agents)
{
var xDocument = new XDocument(
new XDeclaration("1.0", "utf-8", null),
new XElement("COREBASE",
agents.Select(a =>
new XElement("AGENT",
new XElement("AGENT_INDEX", a.Index),
new XElement("AGENT_PORTER_INDEX", a.PorterIndex),
new XElement("AGENT_NAME", a.Name),
new XElement("AGENT_SURNAME", a.Surname),
new XElement("AGENT_MOBILE_NUMBER", a.Mobile)
)
)
)
);
xDocument.Save(_xmlAgentsFile);
}
}
The form can now concentrate on the editing logic. The form does not even need to know what kind of repository to use if you inject the repository in the form constructor (of cause the form constructor must declare a parameter of type IAgentRepository):
var myAgentForm = new AgentForm(new AgentXmlRepository("AgentBase.xml"));
myAgentForm.Show();
UPDATE #2
Note that you cannot change a single item within an XML file. You must load all the agents, make an edit and then rewrite the whole file, even if you edited only one agent.
To do this, you can use my LoadAgents method, then pick an agent from the returned list, edit the agent and finally write the agents list back to the file with my Save method. You can find an agent in the list with LINQ:
Agent a = agents
.Where(a => a.Index == x)
.FirstOrDefault();
This returns null if an agent with the required index does not exist. Since Agent is a reference type, you don’t have to write it back to the list. The list is keeping a reference to the same agent as the variable a.
I have code which takes in data from Flickrs Rest service and populates a ListView. This code works fine and when I run my app I can search for photos and be displayed a list of them. However I want to then get a single photos data but when I try to access this data from the ListView it's completely empty (Iv debugged it and it just contains null entries). I don't have a lot of experience with C# so could anyway advise me as to why I would be getting null results?
private async void ParseFlickrResponse(HttpResponseMessage response)
{
XDocument xml = XDocument.Parse(await response.Content.ReadAsStringAsync());
var photos = from results in xml.Descendants("photo")
select new FlickrImage
{
ImageId = results.Attribute("id").Value.ToString(),
FarmId = results.Attribute("farm").Value.ToString(),
ServerId = results.Attribute("server").Value.ToString(),
Secret = results.Attribute("secret").Value.ToString(),
Title = results.Attribute("title").Value.ToString()
};
FlickrListView.ItemsSource = photos;
}
EDITED
Current code:
enter code here:
private async void ParseFlickrResponse(HttpResponseMessage response)
{
XDocument xml = XDocument.Parse(await response.Content.ReadAsStringAsync());
var photos = from results in xml.Descendants("photo").ToList()
select new FlickrImage
{
ImageId = results.Attribute("id").Value.ToString(),
FarmId = results.Attribute("farm").Value.ToString(),
ServerId = results.Attribute("server").Value.ToString(),
Secret = results.Attribute("secret").Value.ToString(),
Title = results.Attribute("title").Value.ToString()
};
FlickrListView.ItemsSource = new ObservableCollection<FlickrImage>(photos);
}
private void GetPhotoSource(object sender, ItemClickEventArgs e)
{
int inx = FlickrListView.SelectedIndex;
// FlickrImage t = lst.First();
FlickrImage t = lst.ElementAt(inx);
MyImage.Source = new BitmapImage(new Uri(t.ImageUrl.ToString(), UriKind.Absolute));
}
Try adding a .ToList() at the end of your LINQ.
*EDIT (comments summary)
You are handling ItemClick event which seems to be raised before the selection properties on the ListViewBase change. Since these are not updated at this point - you can check e.ClickedItem and cast it to FlickrImage to get your clicked item.
If you do want to work with selection properties - you should be handling the SelectionChanged event.
update
I'm writing a silverlight application and I have the following Class "Home", in this class a read a .xml file a write these to a ListBox. In a other class Overview I will show the same .xml file. I know it is stupid to write the same code as in the class "Home".
The problem is, how to reach these data.
My question is how can I reuse the method LoadXMLFile() from another class?
The code.
// Read the .xml file in the class "Home"
public void LoadXMLFile()
{
WebClient xmlClient = new WebClient();
xmlClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(XMLFileLoaded);
xmlClient.DownloadStringAsync(new Uri("codeFragments.xml", UriKind.RelativeOrAbsolute));
}
private void XMLFileLoaded(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error == null)
{
string xmlData = e.Result;
XDocument xDoc = XDocument.Parse(xmlData);
var tagsXml = from c in xDoc.Descendants("Tag") select c.Attribute("name");
List<Tag> lsTags = new List<Tag>();
foreach (string tagName in tagsXml)
{
Tag oTag = new Tag();
oTag.name = tagName;
var tags = from d in xDoc.Descendants("Tag")
where d.Attribute("name").Value == tagName
select d.Elements("oFragments");
var tagXml = tags.ToArray()[0];
foreach (var tag in tagXml)
{
CodeFragments oFragments = new CodeFragments();
oFragments.tagURL = tag.Attribute("tagURL").Value;
//Tags.tags.Add(oFragments);
oTag.lsTags.Add(oFragments);
}
lsTags.Add(oTag);
}
//List<string> test = new List<string> { "a","b","c" };
lsBox.ItemsSource = lsTags;
}
}
Create a class to read the XML file, make references to this from your other classes in order to use it. Say you call it XmlFileLoader, you would use it like this in the other classes:
var xfl = new XmlFileLoader();
var data = xfl.LoadXMLFile();
If I were you, I would make the LoadXMLFile function take a Uri parameter to make it more reusable:
var data = xfl.LoadXMLFile(uriToDownload);
You could create a class whose single responsibility is loading XML and returning it, leaving the class that calls your LoadXmlFile method to determine how to handle the resulting XML.