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));
.....
}
Related
I have tried to setup a Dialogue tree within unity using XML (I have not used XML much before so am unsure if the way i am going is correct at all)
So I am trying to get the first text element from this dialogue tree but when i call the XML file and say where it is i am getting the everything stored in that branch.
Am i using the correct .XML to be able to do this also as i seen people say use .XML.LINQ or .XML.Serialization not just .XML is this correct for my case ??
Code:
using UnityEngine;
using System.Collections;
using System.IO;
using System.Xml;
using UnityEngine.UI;
using System.Collections.Generic;
public class DialogTree
{
public string text;
public List<string> dialogText;
public List<DialogTree> nodes;
public void parseXML(string xmlData)
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(new StringReader(xmlData));
XmlNode node = xmlDoc.SelectSingleNode("dialoguetree/dialoguebranch");
text = node.InnerXml;
XmlNodeList myNodeList = xmlDoc.SelectNodes("dialoguebranch/dialoguebranch");
foreach (XmlNode node1 in myNodeList)
{
if (node1.InnerXml.Length > 0)
{
DialogTree dialogtreenode = new DialogTree();
dialogtreenode.parseXML(node1.InnerXml);
nodes.Add(dialogtreenode);
}
}
}
}
And here is a picture of the XML.
So i am trying to grab the first element of text then late on there response it will go to branch 1 or 2
<?xml version='1.0'?>
<dialoguetree>
<dialoguebranch>
<text>Testing if the test prints</text>
<dialoguebranch>
<text>Branch 1</text>
<dialoguebranch>
<text>Branch 1a</text>
</dialoguebranch>
<dialoguebranch>
<text>Branch 1b</text>
</dialoguebranch>
</dialoguebranch>
<dialoguebranch>
<text>Branch 2</text>
</dialoguebranch>
</dialoguebranch>
</dialoguetree>
You're getting everything in that branch because XmlNode.InnerXML returns everything in that node. See the documentation for more information on that.
You should use the branch as the base for only looking at its children, instead of starting at xmlDoc every time. Also, you need an entry point to get inside of the first dialoguetree element and then ignore that. Finally, I would only create one XmlDocument and just pass around nodes in your recursion.
Altogether, this might look like this:
public class DialogTree
{
public string text;
public List<DialogTree> nodes = new List<DialogTree>();
public static DialogTree ParseXMLStart(string xmlData)
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(new Stringreader(xmlData));
XmlNode rootNode = xmlDoc.SelectSingleNode("dialoguetree/dialoguebranch");
DialogTree dialogTree = new DialogTree();
dialogTree.ParseXML(rootNode);
return dialogTree;
}
public void ParseXML(XmlNode parentNode)
{
XmlNode textNode = parentNode.SelectSingleNode("text");
text = textNode.InnerText;
XmlNodeList myNodeList = parentNode.SelectNodes("dialoguebranch");
foreach (XmlNode curNode in myNodeList)
{
if (curNode.InnerXml.Length > 0)
{
DialogTree dialogTree = new DialogTree();
dialogTree.ParseXML(curNode);
nodes.Add(dialogTree);
}
}
}
}
And you could use it like so:
string xmlStringFromFile;
DialogTree dialogue = DialogTree.ParseXMLStart(xmlStringFromFile);
All of this code is untested but I hope the general idea is clear. Let me know if you find any errors in the comments below and I will try to fix them.
im unable to delete an xml node from a xml file. Im unable to figure out what is the issue in my code. I have attached my code
class Program
{
static void Main(string[] args)
{
XmlDocument xDoc=new XmlDocument();
xDoc.Load(#"C:\Users\MyUser\Desktop\Family.xml");
//try 1
XmlNode firstNode=xDoc.SelectSingleNode("Apartments/Family[Father='Father1']");
xDoc.LastChild.RemoveChild(firstNode);
xDoc.RemoveAll();
//Try2
XmlNodeList nodeColl = xDoc.GetElementsByTagName("Apartments/Family");
foreach (XmlNode xNode in nodeColl)
{
if (xNode["Father"].InnerText == "Father1")
{
xNode.ParentNode.RemoveChild(xNode);
}
}
// firstNode.ParentNode.RemoveChild(firstNode);
}
}
the Xml document format is
<?xml version="1.0"?>
<Apartments>
<Family>
<Father>Father1</Father>
<Mother>Mother1</Mother>
<Daughter>Daughter1</Daughter>
<Son>Son1</Son>
</Family>
<Family>
<Father>Father2</Father>
<Mother>Mother2</Mother>
<Daughter>Daughter2</Daughter>
<Son>Son2</Son>
</Family>
<Family>
<Father>Father3</Father>
<Mother>Mother3</Mother>
<Daughter>Daughter3</Daughter>
<Son>Son3</Son>
</Family>
<Family>
<Father>Father4</Father>
<Mother>Mother4</Mother>
<Daughter>Daughter4</Daughter>
<Son>Son4</Son>
</Family>
</Apartments>
Please let me know where im wrong.
After the modifications you need to save the changes to file.
XmlDocument xDoc=new XmlDocument();
xDoc.Load(#"C:\Users\MyUser\Desktop\Family.xml");
XmlNodeList nodeColl = xDoc.GetElementsByTagName("Apartments/Family");
foreach (XmlNode xNode in nodeColl)
{
if (xNode["Father"].InnerText == "Father1")
{
xNode.ParentNode.RemoveChild(xNode);
}
}
// save the changes back to file
xDoc.Save(#"C:\Users\MyUser\Desktop\Family.xml");
I have one xml file whic I need to edit, It looks like:
<?xml version="1.0" encoding="UTF-8"?>
<PaketniUvozObrazaca xmlns="urn:PaketniUvozObrazaca_V1_0.xsd">
<PodaciOPoslodavcu>
<JIBPoslodavca>XXXXXXXXXX</JIBPoslodavca>
<NazivPoslodavca>Comapyn</NazivPoslodavca>
<BrojZahtjeva>1307</BrojZahtjeva>
<DatumPodnosenja>2013-03-19</DatumPodnosenja>
</PodaciOPoslodavcu>
<Obrazac1022>
<Dio1PodaciOPoslodavcuIPoreznomObvezniku>
<JIBJMBPoslodavca>XXXXXXXXXX</JIBJMBPoslodavca>
<Naziv>Compyny</Naziv>
<AdresaSjedista>Adress </AdresaSjedista>
<JMBZaposlenika>XXXXXXX</JMBZaposlenika>
<ImeIPrezime>ad</ImeIPrezime>
<AdresaPrebivalista>City</AdresaPrebivalista>
<PoreznaGodina>2012</PoreznaGodina>
</Dio1PodaciOPoslodavcuIPoreznomObvezniku>
</Obrazac1022>
</PaketniUvozObrazaca>
If i want to query (select nodes) from this file how I should reffernce namespace ?
static void Main(string[] args)
{
XmlDocument gip = new XmlDocument();
gip.Load("C:\\vs2013tests\\adoGipko\\gip-2012.xml");
XmlNamespaceManager nspm = new XmlNamespaceManager(gip.NameTable);
nspm.AddNamespace("urn", "PaketniUvozObrazaca_V1_0");
foreach (XmlNode uposlnik in gip.SelectNodes("//PaketniUvozObrazaca_V1_0/Obrazac1022", nspm))
{
Console.WriteLine(uposlnik.SelectSingleNode("Dio1PodaciOPoslodavcuIPoreznomObvezniku/ImeIPrezime",nspm).InnerText);
}
Console.ReadKey();
}
You need to give the namespace a name and specify the uri exactly as in the XML. Which name you use is not important:
nspm.AddNamespace("d", "urn:PaketniUvozObrazaca_V1_0.xsd");
You now have to use that name for all the tags:
foreach (XmlNode uposlnik in gip.SelectNodes("//d:PaketniUvozObrazaca/"+
"d:Obrazac1022", nspm))
{
Console.WriteLine(
uposlnik.SelectSingleNode("d:Dio1PodaciOPoslodavcuIPoreznomObvezniku/"+
"d:ImeIPrezime", nspm).InnerText);
}
Furthermore, I fixed the root tag in the query. You used PaketniUvozObrazaca_V1_0 which is part of the namespace. You need to use PaketniUvozObrazaca, which is the root tag.
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.
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.