I have made a script in C# that should load data from a XML file into a ListView.
This is the XML file I used to test :
<?xml version="1.0" encoding="utf-8"?>
<Items>
<wordExample languageOne="Пока" languageTwo="Doei" languageThree="Goodbye" />
<wordExample languageOne="1" languageTwo="2" languageThree="3" />
<wordExample languageOne="4" languageTwo="5" languageThree="6" />
<wordExample languageOne="7" languageTwo="8" languageThree="9" />
</Items>
Now I get an error when I try to load the XMl into the ListView and I really don't know what it could be, this is actually the first time I try to use XML in C#.
This is the code used to load the XML into the ListView :
public void ImportXMLToListView(ListView listview)
{
DialogResult dr = OPEN_FILE_DIA.ShowDialog();
if (dr == DialogResult.OK)
{
XDocument doc = XDocument.Load(OPEN_FILE_DIA.FileName);
int counter = 0;
foreach (var dm in doc.Descendants("Items"))
{
string tmpOne = dm.Attribute("languageOne").Value;
string tmpTwo = dm.Attribute("languageTwo").Value;
string tmpThree = dm.Attribute("languageThree").Value;
counter++;
ListViewItem lvi;
lvi = new ListViewItem(tmpOne);
lvi.SubItems.Add(tmpTwo);
lvi.SubItems.Add(tmpThree);
listview.Items.Add(lvi);
}
}
}
Am I doing something wrong??
This is the error I get : (Object reference not set to an instance of an object.)
Please tell me what I do wrong I really try to understand :S
language attributes belongs to your wordExample items. You need doc.Descendants("wordExample")
foreach (var dm in doc.Descendants("wordExample"))
{
string tmpOne = (string)dm.Attribute("languageOne");
string tmpTwo = (string)dm.Attribute("languageTwo");
string tmpThree = (string)dm.Attribute("languageThree");
...
}
And you can use explicit cast instead of directly accessing Value property to avoid NullReferenceException.
Related
I'm doing a HttpWebrequest by using c#. I get the following response
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Siri version="1.0" xmlns="http://www.siri.org.uk/">
<ServiceDelivery>
<ResponseTimestamp>2013-03-21T11:40:13.514Z</ResponseTimestamp>
<StopMonitoringDelivery version="1.0">
<ResponseTimestamp>2013-03-21T11:40:13.514Z</ResponseTimestamp>
<RequestMessageRef>12345</RequestMessageRef>
<MonitoredStopVisit>
<RecordedAtTime>2013-03-21T11:40:13.514Z</RecordedAtTime>
<MonitoringRef>020035811</MonitoringRef>
<MonitoredVehicleJourney>
<FramedVehicleJourneyRef>
<DataFrameRef>-</DataFrameRef>
<DatedVehicleJourneyRef>-</DatedVehicleJourneyRef>
</FramedVehicleJourneyRef>
<VehicleMode>bus</VehicleMode>
<PublishedLineName>1</PublishedLineName>
<DirectionName>Kempston</DirectionName>
<OperatorRef>STB</OperatorRef>
<MonitoredCall>
<AimedDepartureTime>2013-03-21T11:41:00.000Z</AimedDepartureTime>
<ExpectedDepartureTime>2013-03-21T11:44:27.000Z</ExpectedDepartureTime>
</MonitoredCall>
</MonitoredVehicleJourney>
</MonitoredStopVisit>
</StopMonitoringDelivery>
</ServiceDelivery>
</Siri>
This response is saved in a string variable called "ResponseFromServer"
Now I just want to show the 'ExpectedDepartureTime' in a listbox
I tried to do this with the following code:
//XMLResponse put in documentRoot
XDocument documentRoot = XDocument.Parse(responseFromServer);
//Linq To XML
var documents =
(from docs in documentRoot.Descendants("ServiceDelivery").Descendants("StopMonitoringDelivery").Descendants("MonitoredStopVisit").Descendants("MonitoredVehicleJourney").Descendants("MonitoredCall")
select new
{
dep = docs.Element("ExpectedDepartureTime").Value
});
//Show every ExpectedDepartureTime
foreach (var i in documents)
{
lstHours.Items.Add(i);
MessageBox.Show(i.ToString());
}
When I try this nothing happens (the messagebox is not appearing and in the listbox i see nothnig). I also try to Descendant first the tag without success...
Can anybody help me with this issue?
Thanks!
You need to specify namespace like this and then use one method Descendants
XNamespace ns = "http://www.siri.org.uk/";
var documents =
documentRoot.Descendants(ns + "MonitoredCall")
.Select(x => x.Element(ns + "ExpectedDepartureTime").Value);
now you can
foreach (var i in documents)
{
lstHours.Items.Add(i);
MessageBox.Show(i.ToString());
}
prints
2013-03-21T11:44:27.000Z
I'm trying to create xml data from my data, creation was successfull but the output is bad how can I fix this issue?
Here is my code:
private void btnGenerate_Click(object sender, EventArgs e)
{
XElement xml = new XElement("Navigation",
new XElement("NavigationSets"));
foreach (DataRow row_navs in GetNavigationSets().Rows)
{
xml.Add(new XElement("NavigationName", row_navs["name"].ToString()));
foreach (DataRow row_sets in GetMenusInNavigationSetByNavigation(2).Rows)
{
if (int.Parse(row_sets["id"].ToString()) == int.Parse(row_navs["id"].ToString()))
{
foreach (DataRow row_menus in GetMenuById(int.Parse(row_sets["menu_id"].ToString())).Rows)
{
xml.Add(new XElement("MenuName", row_menus["name"].ToString()));
}
}
}
}
xml.Save("data.xml");
}
Im expecting an output like this
<?xml version="1.0" encoding="utf-8"?>
<Navigation>
<NavigationSets>
<NavigationName>
<MenuName></MenuName>
</NavigationName>
<NavigationSets/>
</Navigation>
In my current code my output is like this
<?xml version="1.0" encoding="utf-8"?>
<Navigation>
<NavigationSets/>
<NavigationName></NavigationName>
<MenuName></MenuName>
</Navigation>
To add to Jon Skeets answer,
You can also use
using System.Xml.Linq;
to loop through lists so it is all one statement,
new XElement("NavigationSets",
menus.Select(menu => new XElement("MenuName"))
)
Look at when you're adding elements:
xml.Add(new XElement("NavigationName", row_navs["name"].ToString()));
xml.Add(new XElement("MenuName", row_menus["name"].ToString()));
Where xml is this element:
XElement xml = new XElement("Navigation",
new XElement("NavigationSets"));
That means xml is the Navigation element, not the NavigationSets element. I suspect you want something like:
XElement outer = new XElement("Navigation");
XElement inner = new XElement("NavigationSets");
outer.Add(inner);
... then add to inner.
I have this XML document I am trying to read in and insert into a data base. There will only ever be one GamePlay node however GamePlayStep may repeat so I have created a node list for this. For some reason GamePlayStep isn't receiving data. Here is the XML file:
<?xml version="1.0" encoding="utf-8" ?>
<GameData>
<GamePlay>
<type>add</type>
<GamePlayID>1</GamePlayID>
<ParticipantID>1</ParticipantID>
<GameID>1</GameID>
<GameDifficultyID>1</GameDifficultyID>
<Start>2012-08-06T12:19:33.154Z</Start>
<End>2012-08-06T12:30:33.154Z</End>
<Success>False</Success>
</GamePlay>
<GamePlayStep>
<GamePlayStepID>1</GamePlayStepID>
<Start>2012-08-06T12:19:33.154Z</Start>
<End>2012-08-06T12:30:33.154Z</End>
<SortOrder>1</SortOrder>
<Score>1</Score>
<hintUsed>True</hintUsed>
<GamePause>
<GamePauseID>1</GamePauseID>
<Start>2012-08-06T12:19:33.154Z</Start>
<End>2012-08-06T12:30:33.154Z</End>
<Order>1</Order>
<Duration>05:01</Duration>
</GamePause>
</GamePlayStep>
</GameData>
Here is my code:
public static void start()
{
string[] filePaths = Directory.GetFiles(System.Configuration.ConfigurationManager.ConnectionStrings["filePath"].ConnectionString);
List<GamePlay> gameObj = new List<GamePlay>();
List<GamePlayStep> gameStepObj = new List<GamePlayStep>();
foreach (string value in filePaths)
{
XmlDocument xd = new XmlDocument();
XmlNodeList GameSteps;
xd.Load(value);
XmlNode documentNode = xd.SelectSingleNode("/GameData/GamePlay");
GameSteps = xd.SelectNodes("/GameData/GamePlay/GamePlayStep");
GamePlay newGamePlay = new GamePlay();
newGamePlay.setType(Convert.ToString(documentNode.SelectSingleNode("type").InnerText));
newGamePlay.setGamePlayID(Convert.ToInt32(documentNode.SelectSingleNode("GamePlayID").InnerText));
newGamePlay.setParticipantID(Convert.ToInt32(documentNode.SelectSingleNode("ParticipantID").InnerText));
newGamePlay.setGameDifficultyID(Convert.ToInt32(documentNode.SelectSingleNode("GameDifficultyID").InnerText));
newGamePlay.setGameID(Convert.ToInt32(documentNode.SelectSingleNode("GameID").InnerText));
newGamePlay.setStartDateTime(Convert.ToDateTime(documentNode.SelectSingleNode("Start").InnerText));
newGamePlay.setEndDateTime(Convert.ToDateTime(documentNode.SelectSingleNode("End").InnerText));
newGamePlay.setSuccess(Convert.ToBoolean(documentNode.SelectSingleNode("Success").InnerText));
newGamePlay.setFile(value);
newGamePlay.addNewGamePlay();
foreach (XmlNode documentNode2 in GameSteps)
{
GamePlayStep newGamePlayStep = new GamePlayStep();
newGamePlayStep.setGamePlayStepID(Convert.ToInt32(documentNode2.SelectSingleNode("GamePlayStepID").InnerText));
newGamePlayStep.setGamePlayID(newGamePlay.getGamePlayID());
newGamePlayStep.setStartDateTime(Convert.ToDateTime(documentNode2.SelectSingleNode("Start").InnerText));
newGamePlayStep.setEndDateTime(Convert.ToDateTime(documentNode2.SelectSingleNode("End").InnerText));
newGamePlayStep.setOrderPlayed(Convert.ToInt32(documentNode2.SelectSingleNode("SortOrder").InnerText));
newGamePlayStep.setScore(Convert.ToInt32(documentNode2.SelectSingleNode("Score").InnerText));
newGamePlayStep.setHintUsed(Convert.ToBoolean(documentNode2.SelectSingleNode("hintUsed").InnerText));
newGamePlayStep.addNewGamePlayStep();
}
}
}
The GamePlay is filling the variables properly and inserting into the database however the GamePlaySteps in the NodeList are not. Does anyone see the problem or how I can improve this?
Thanks.
Your XPath for accessing the GamePlayStep is incorrect;
It should be:
GameSteps = xd.SelectNodes("/GameData/GamePlayStep");
As GamePlayStep is a child of GameData, not GamePlay, in your document.
Use LINQ2XML....its simple and cool
XElement doc=XElement.Load("yourXml");
newGamePlay.setType(doc.Descendants("GameData").Element("GamePlay").Element("type").Value);
....
foreach (Element eml in doc.Descendants("GameData").Elements("GamePlayStep"))
{
GamePlayStep newGamePlayStep = new GamePlayStep();
newGamePlayStep.setGamePlayStepID(Convert.ToInt32(elm.Element("GamePlayStepID").Value));
newGamePlayStep.setStartDateTime(Convert.ToDateTime(elm.Element("Start").Value));
.....
}
XML:
<CONFIGURATION>
<Files>
<File>D:\Test\TestFolder\TestFolder1\TestFile.txt</File>
<File>D:\Test\TestFolder\TestFolder1\TestFile01.txt</File>
<File>D:\Test\TestFolder\TestFolder1\TestFile02.txt</File>
<File>D:\Test\TestFolder\TestFolder1\TestFile03.txt</File>
<File>D:\Test\TestFolder\TestFolder1\TestFile04.txt</File>
</Files>
<SizeMB>3</SizeMB>
<BackupLocation>D:\Log backups\File backups</BackupLocation>
</CONFIGURATION>
Code:
private void btnLinq_Click(object sender, EventArgs e)
{
queryData(#"D:\WatchMe1\backupconfig1.xml");
}
static void queryData(string xmlFile)
{
var xdoc = XDocument.Load(xmlFile);
var configuration = xdoc.Element("CONFIGURATION");
string sizeMB = configuration.Element("SizeMB").Value;
string backupLocation = configuration.Element("BackupLocation").Value;
//need a code here to check if element <File> exist before executing the file array
string[] files = configuration.Element("Files").Elements("File").Select(c => c.Value).ToArray();
foreach (string file in files)
{
Console.WriteLine(file);
}
}
I have an xml writer program that edits the above xml. The Files element can be changed to Folder element. I have another program that reads the values(file locations) and do something with it, I have to check first if the element is a Files or Folders element.
You can check for element existence with something like
if(configuration.Elements("...").Any()){...}
But i'm not sure what you are asking here exactly...
This may be what you want to do:
if(configutation.Elements.First("Files") != null)
{
string[] files = configuration.Element("Files").Elements("File").Select(c => c.Value).ToArray();
}
Hope this helps!
private void BindCountry()
{
XmlDocument doc = new XmlDocument();
doc.Load(Server.MapPath("countries.xml"));
foreach (XmlNode node in doc.SelectNodes("//country"))
{
usrlocationddl.Items.Add(new ListItem(node.InnerText, node.Attributes["codes"].InnerText));
}
}
The above code am using for loading countries List from an xml file into a dropdown list. But while doing so am encountering a Null Reference error.
Object reference not set to an
instance of an object.
Contents of the xml file:
<countries>
<country code="AF" iso="4">Afghanistan</country>
<country code="AL" iso="8">Albania</country>
</countries>
Where in the code should I be changing, so that I can escape the error.
I suspect the problem is that you've got a country with no "codes" attribute. You could avoid that like this:
private void BindCountry()
{
XmlDocument doc = new XmlDocument();
doc.Load(Server.MapPath("countries.xml"));
foreach (XmlNode node in doc.SelectNodes("//country"))
{
XmlAttribute attr = node.Attributes["codes"];
if (attr != null)
{
usrlocationddl.Items.Add(new ListItem(node.InnerText, attr.Value));
}
}
}
If that doesn't help, I suggest you write a simple console application to try to load the XML and write out each entry you'd select - that should make it easier to work out what's going wrong.