I keep getting errors with this, and can't see what I'm doing wrong.
Here's the code
private void _FixSave_Offline_Load(object sender, EventArgs e)
{
System.Xml.XmlDocument NewGame = new System.Xml.XmlDocument();
NewGame.Load(Application.StartupPath + "//Files//Checks_Offline.xml");
foreach (System.Xml.XmlNode nameNode in NewGame.SelectNodes("//Games//NewGame"))
{
listView1.Items.Add(nameNode.Attributes["Name"].InnerText);
}
}
And here is the XML Layout
<Games>
<NewGame>
<Name></Name>
<Check></Check>
<Static></Static>
<Location></Location>
<Start></Start>
<Length></Length>
<FoundBy></FoundBy>
<Verified></Verified>
</NewGame>
Here's is the error I keep getting
and visual studio highlights the following code:
listView1.Items.Add(nameNode.Attributes["Name"].InnerText);
I've tried using not only "//" but also "/" so anything that will fix this will be more than welcome, b/c I can't for the life of me see what I'm doing wrong.
At a glance, you're looking for an attribute with the name of "Name", but there are no attributes on any of the XML elements in your example.
I believe you want the content of the Name node:
foreach (System.Xml.XmlNode nameNode in NewGame.SelectNodes("//Games//NewGame/Name"))
{
listView1.Items.Add(nameNode.Value);
}
You might have to play with the XPath expression a bit, depending on the actual structure of your XML document.
I couldn't see your XML example for some reason, but make sure you are distinguishing between Elements and Attributes
Also, make sure that the attribute/element is spelled "Name" exactly. I believe it is case sensitive.
--
Edit: Now I am able to view your XML, it appears that "Name" is actually an element, rather than an attribute.
Try using the Item property, or the Value property instead of nameNode.Attributes.
I got it to work. Turns out that I the error was due to virtuallist = true. Tim I modified your code above just a little to get the result I wanted. Here's the code for anyone to use for future ref.
private void _FixSave_Offline_Load(object sender, EventArgs e)
{
System.Xml.XmlDocument NewGame = new System.Xml.XmlDocument();
NewGame.Load(Application.StartupPath + "//Files//Checks_Offline.xml");
foreach (System.Xml.XmlNode nameNode in NewGame.SelectNodes("//Games//NewGame/Name"))
{
listView1.Items.Add(nameNode.InnerText);
}
}
And here's a quick screenshot for the given result.
Hope this helps others as well. Thanks to the above people who commented me on this, and big thanks to Tim.
Related
I am trying to get the value of the div class "darkgreen" which is 46.98. I tried the following code but am getting a Null exception.
Below is the code I am trying:
private void button1_Click(object sender, EventArgs e)
{
var doc = new HtmlWeb().Load("https://rotogrinders.com/grids/nba-defense-vs-position-cheat-sheet-1493632?site=fanduele");
HtmlAgilityPack.HtmlNodeCollection nodes = doc.DocumentNode.SelectNodes("//div[#class='darkgreen']");
foreach (HtmlAgilityPack.HtmlNode node in nodes)
{
Console.WriteLine(node.InnerText);
}
}
If I run the same code but with doc.DocumentNode.SelectNodes("//div[#class='rgt-hdr colorize']") it does pull the header data with no error.
I am thinking that maybe child nodes may be a solution but I am not sure as I am unable to get it to work still.
Your problem is that the HTML your looking it is created by a javascript. And the HTML you load into your Document variable is pre-what-ever is created by the javascript. If you look at the page source in your web browser you will see the exact HTML that gets loaded in your HtmlDocument variable.
The example below will give you the data(JSON) that is used to create the table. I don't know whether that is enough for whatever you're trying to do.
public static void Main(string[] args)
{
Console.WriteLine("Program Started!");
HtmlDocument doc;
doc = new HtmlWeb().Load("https://rotogrinders.com/grids/nba-defense-vs-position-cheat-sheet-1493632?site=fanduele");
HtmlNode node = doc.DocumentNode.SelectSingleNode("//section[#class='bdy content article full cflex reset long table-page']/following-sibling::script[1]");
int start = node.InnerText.IndexOf("[");
int length = node.InnerText.IndexOf("]") - start +1;
Console.WriteLine(node.InnerText.Substring(start, length));
Console.WriteLine("Program Ended!");
Console.ReadKey();
}
Alternative solution
Alternatively you can use Selenium with PhantomJS. And then load the HTML from the headless browser into your document variable and then your xpath will work.
I have an XML file that collects information with Button_Click, so it starts off empty.
XML Sample
<marina>
<dockone>
</dockone>
<docktwo>
</docktwo>
</marina>
When I submit information from a textbox, a new XmlNode is created called slipone, and another XmlNode called reg is nested within that.
XML Sample 2
<marina>
<dockone>
<slipone>
<reg>12345</reg>
<slipone>
</dockone>
<docktwo>
</docktwo>
</marina>
I have attempted to create an if/else statement that will add a new XmlNode called sliptwo, with reg still nested within it, if slipone already has text, like so:
<marina>
<dockone>
<slipone>
<reg>12345</reg>
<slipone>
<sliptwo>
<reg>67890</reg>
<sliptwo>
</dockone>
<docktwo>
</docktwo>
</marina>
However the closest I have gotten is another XMlnode is still created, however it labels itself as slipone, and I am not sure what I am doing wrong:
<marina>
<dockone>
<slipone>
<reg>12345</reg>
<slipone>
<slipone>
<reg>67890</reg>
<slipone>
</dockone>
<docktwo>
</docktwo>
</marina>
This is an example of what I have been playing around with. Ignore the operators as I have resorted to trial and error but still have gotten nowhere. Please help!
C# Example
XmlDocument XmlDocObj1 = new XmlDocument();
XmlDocObj1.Load(Server.MapPath("~/App_Data/SlipData.xml"));
XmlNode rootnode1 = XmlDocObj1.SelectSingleNode("marina/dockone");
XmlNode dockone = rootnode1.AppendChild(XmlDocObj1.CreateNode(XmlNodeType.Element, "slipone", ""));
XmlNode docktwo = rootnode1.AppendChild(XmlDocObj1.CreateNode(XmlNodeType.Element, "sliptwo", ""));
XmlNode dockthree = rootnode1.AppendChild(XmlDocObj1.CreateNode(XmlNodeType.Element, "slipthree", ""));
if (regfinal.Text != dockone.InnerText)
{
dockone.AppendChild(XmlDocObj1.CreateNode(XmlNodeType.Element, "Reg", "")).InnerText = regfinal.Text;
XmlDocObj1.Save(Server.MapPath("/App_Data/SlipData.xml"));
}
else if (regfinal.Text == dockone.InnerText)
{
docktwo.AppendChild(XmlDocObj1.CreateNode(XmlNodeType.Element, "Reg", "")).InnerText = regfinal.Text;
XmlDocObj1.Save(Server.MapPath("/App_Data/SlipData.xml"));
}
Your logic isn't going to do what I think you are saying since the only time (regfinal.Text != dockone.InnerText) will evaluate to false is when you enter nothing in your text control.
I believe you might mean to say if dockone exists then create another node called docktwo. This will require you to change your logic.
Some very simple code to get you a bit farther down the path. Not intended to be perfect or solve all problems...
private void button1_Click(object sender, EventArgs e)
{
XmlDocument XmlDocObj1 = new XmlDocument();
XmlDocObj1.Load(AppDomain.CurrentDomain.BaseDirectory.ToString()+"test.xml");
XmlNode rootnode1 = XmlDocObj1.SelectSingleNode("marina/dockone");
XmlNode dockone = rootnode1.AppendChild(XmlDocObj1.CreateNode(XmlNodeType.Element, "slipone", ""));
XmlNode docktwo = rootnode1.AppendChild(XmlDocObj1.CreateNode(XmlNodeType.Element, "sliptwo", ""));
XmlNode dockthree = rootnode1.AppendChild(XmlDocObj1.CreateNode(XmlNodeType.Element, "slipthree", ""));
//jsh: old logic
//if (textBox1.Text != dockone.InnerText)
//new logic to test whether we have already created the dockone node which should only occur once
//you already have the logic for selecting the dockone node above...now just test if you already have it.
//NOTE: you may actually want a switch statement given that you avhe dockone, docktwo, and dockthree or at least another
// if statement to see if docktwo has been created and thus creaste dockthree.
if (rootnode1 == null )
{
dockone.AppendChild(XmlDocObj1.CreateNode(XmlNodeType.Element, "Reg", "")).InnerText = textBox1.Text;
XmlDocObj1.Save(AppDomain.CurrentDomain.BaseDirectory.ToString() + "test.xml");
}
//else if (textBox1.Text == dockone.InnerText) jsh: old logic
else
{
docktwo.AppendChild(XmlDocObj1.CreateNode(XmlNodeType.Element, "Reg", "")).InnerText = textBox1.Text;
XmlDocObj1.Save(AppDomain.CurrentDomain.BaseDirectory.ToString() + "test.xml");
}
}
So I am starting to learn how to use XML data within a app and decided to use some free data to do this however I cannot for the life of me get it working this is my code so far. (I have done a few apps with static data before but hey apps are designed to use the web right? :p)
public partial class MainPage : PhoneApplicationPage
{
List<XmlItem> xmlItems = new List<XmlItem>();
// Constructor
public MainPage()
{
InitializeComponent();
LoadXmlItems("http://hatrafficinfo.dft.gov.uk/feeds/datex/England/CurrentRoadworks/content.xml");
test();
}
public void test()
{
foreach (XmlItem item in xmlItems)
{
testing.Text = item.Title;
}
}
public void LoadXmlItems(string xmlUrl)
{
WebClient client = new WebClient();
client.OpenReadCompleted += (sender, e) =>
{
if (e.Error != null)
return;
Stream str = e.Result;
XDocument xdoc = XDocument.Load(str);
***xmlItems = (from item in xdoc.Descendants("situation id")
select new XmlItem()
{
Title = item.Element("impactOnTraffic").Value,
Description = item.Element("trafficRestrictionType").Value
}).ToList();***
// close
str.Close();
// add results to the list
xmlItems.Clear();
foreach (XmlItem item in xmlItems)
{
xmlItems.Add(item);
}
};
client.OpenReadAsync(new Uri(xmlUrl, UriKind.Absolute));
}
}
I am basically trying to learn how to do this at the moment as I am intrigued how to actually do it (I know there are many ways but ATM this way seems the easiest) I just don't get what the error is ATM. (The bit in * is where it says the error is)
I also know the display function ATM is not great (As it will only show the last item) but for testing this will do for now.
To some this may seem easy, as a learner its not so easy for me just yet.
The error in picture form:
(It seems I cant post images :/)
Thanks in advance for the help
Edit:
Answer below fixed the error :D
However still nothing is coming up. I "think" it's because of the XML layout and the amount of descendants it has (Cant work out what I need to do being a noob at XML and pulling it from the web as a data source)
Maybe I am starting too complicated :/
Still any help/tips on how to pull some elements from the feed (As there all in Descendants) correctly and store them would be great :D
Edit2:
I have it working (In a crude way) but still :D
Thanks Adam Maras!
The last issue was the double listing. (Adding it to a list, to then add it to another list was causing a null exception) Just using the 1 list within the method solved this issue, (Probably not the best way of doing it but it works for now) and allowed for me to add the results to a listbox until I spend some time working out how to use ListBox.ItemTemplate & DataTemplate to make it look more appealing. (Seems easy enough I say now...)
Thanks Again!!!
from item in xdoc.Descendants("situation id")
// ^
XML tag names can't contain spaces. Looking at the XML, you probably just want "situation" to match the <situation> elements.
After looking at your edit and further reviewing the XML, I figured out what the problem is. If you look at the root element of the document:
<d2LogicalModel xmlns="http://datex2.eu/schema/1_0/1_0" modelBaseVersion="1.0">
You'll see that it has a default namespace applied. The easiest solution to your problem will be to first get the namespsace from the root element:
var ns = xdoc.Root.Name.Namespace;
And then apply it wherever you're using a string to identify an element or attribute name:
from item in xdoc.Descendants(ns + "situation")
// ...
item.Element(ns + "impactOnTraffic").Value
item.Element(ns + "trafficRestrictionType").Value
One more thing: <impactOnTraffic> and <trafficRestrictionType> aren't direct children of the <situation> element, so you'll need to change that code as well:
Title = items.Descendants(ns + "impactOnTraffic").Single().Value,
Description = item.Descendants(ns + "trafficRestrictionType").Single().Value
I've come across a SharePoint problem that I hope someone can help with. Basically, when I am trying to add a column called "MigratedChemist" to a list called "WorkCards" (pListName in the method parameters). No matter what I try I am getting a FaultException error raised when calling UpdateList. I am connecting using the SharePoint web service. I have confirmed the following:
The column doesn't already exist and I do have permissions to create it in SharePoint
The connection to SharePoint is established corectly to /_vti_bin/lists.asmx
The list name is correct as I have another method which returns items from the list and that works perfectly.
The xVersion and xId values are set correctly when the program runs and passed as parameters - as far as I am concerned I should just be able to pass the list name, as opposed to the GUID, but neither method works.
My code is as follows:
public static bool AddColumnToList(string pUri, string pListName, string pViewName, string pMaxRecords)
{
string version = string.Empty;
XAttribute xId = null;
XAttribute xVersion = null;
try
{
XElement listDetails = client.GetList(pListName);
xVersion = listDetails.Attribute("Version");
xId = listDetails.Attribute("ID");
}
catch { throw; }
XElement ndNewFields = new XElement ("Fields", "");
string newXml = "<Method ID='1' Cmd='New'><Field Name='MigratedChemist' Type='Text' DisplayName='MigratedChemist' /></Method></Fields>";
ndNewFields.Add(newXml);
XElement result;
try
{
result = client.UpdateList(xId.Value, null, ndNewFields, null, null, xVersion.Value);
}
catch (FaultException fe)
{
}
return true;
}
In addition to this does anyone know how to get any decent information from FaultRequest? At the moment I get the following error message, which is of no use and there appears to be no extra detail. I have tried, as some have suggested removing the error handling and letting the program halt, but that doesn't give me any extra information either.
{"Exception of type 'Microsoft.SharePoint.SoapServer.SoapServerException' was thrown."}
For future reference I have solved both the problem of the SharePoint update failing AND the FaultException problem, so am including it here for posterity:
Problem 1 - Problem with UpdateList
This problem was caused because my XML was malformed. When I called ndNewFields.Add(newXml) then XML that was being returned was replacing < and > than with control characters, as shown below (I have added an extra space because this editor converts them automatically.
<Method ID="1" Cmd="New"> ;< ;Field Name="MigratedChemist"> ;< ;/Field> ;< ;/Method> ;
Now, I did notice this pretty early on but wasn't sure whether it would cause a problem or not. However using the XElement.Parse command I was able to remove these characters and this resolved the problem:
ndNewFields.Add(XElement.Parse (newXml));
Problem 2 - Problem with the SharePoint error coming back as FaultException
This has been bugging for me ages so I am glad I have finally solved it. I can't take credit for it, as I took it from another page, but the following code was how I got the details.
catch (FaultException fe)
{
MessageFault msgFault = fe.CreateMessageFault();
XmlElement elm = msgFault.GetDetail<XmlElement>();
}
Hopefully this will save someone some frustration in the future!
Andrew
I need to set up infopath screentip programmatically in infopath code behind. I read something about this that it is impossible but, i made something like this:
XPathNavigator field1 = MainDataSource.CreateNavigator().SelectSingleNode(xpath1, NamespaceManager);
XPathNavigator field2 = MainDataSource.CreateNavigator().SelectSingleNode(xpath2, NamespaceManager);
if (field1.Value.ToString() == "none")
{
this.Errors.Add(field2, "XXX", "XXxxxXX", "xxXXxxXX");
}
but still i change the field to "cannot be blank" any clue ?
I faced the exact same problem like you and didn't really find an easy and clean solution. I had to check if an IBAN was entered correctly. Working with extra fields and methods is not clean enough for me so I went and tried it through the Errors-property, which you say doesn't work. Here's the code I used:
XPathNavigator navigator = MainDataSource.CreateNavigator();
XPathNavigator ibanField = navigator.SelectSingleNode("/my:.../my:.../my:FldIban", NamespaceManager);
Errors.Add(ibanField , "Invalid IBAN", "The given IBAN is not formatted correctly");
Hope this helps anyway, it did for me. :)
I created button and special field with hide when value = true , and show when is true.
public void CTRL32_7_Clicked(object sender, ClickedEventArgs e)
{
// XPathNavigator test = MainDataSource.CreateNavigator().SelectSingleNode("/my:myFields/my:field11", NamespaceManager);
XPathNavigator test2 = MainDataSource.CreateNavigator().SelectSingleNode("my:myFields/my:buttonSet", NamespaceManager);
if (test2.Value == "FALSE")
{
test2.SetValue("TRUE");
}
else
{
test2.SetValue("FALSE");
}
XPathNavigator tooltip = MainDataSource.CreateNavigator().SelectSingleNode("my:myFields/my:tooltip", NamespaceManager);
tooltip.SetValue("Custom Tooltip DEMO");
}