Array in C# with data of XML - c#

I get a XML and I want to get the value of Role to make an array in C#, and then remove the same value to make another one.xml goes here:
<Phrase Role="2"></Phrase>
<Phrase Role="2"></Phrase>
<Phrase Role="1"></Phrase>
<Phrase Role="1"></Phrase>
<Phrase Role="2"></Phrase>
<Phrase Role="1"></Phrase>
<Phrase Role="2"></Phrase>
Here is my start up, I get all the Role, but when I add them in to an array it doesn't show the value of the Role, just get System.Int32[].
The load xml and transform to class code goes here:
XmlDocument doc = new XmlDocument();
doc.LoadXml("<Phrase Role="2"></Phrase>
<Phrase Role="2"></Phrase>
<Phrase Role="1"></Phrase>
<Phrase Role="1"></Phrase>
<Phrase Role="2"></Phrase>
<Phrase Role="1"></Phrase>
<Phrase Role="2"></Phrase>");
//get all the phrases
XmlNodeList phrases = xml.GetElementsByTagName("Phrase");
foreach (XmlNode phraseNode in phrases)
{
Phrase phrase = NodeToPhrase(phraseNode);
phrasesList.Add(phrase);
}
//Phrase node to phrase
private Phrase NodeToPhrase(XmlNode node)
{
Phrase phrase = new Phrase();
XmlNode roleNode = node.Attributes["Role"];
if (roleNode != null && !string.IsNullOrEmpty(roleNode.Value))
phrase.Role = roleNode.Value;
return phrase;
}
//Crate a phrase class
public Dictionary<string, Phrase> Phrases = new Dictionary<string, Phrase>();
public class Phrase
{
public string Role = null;
}
My create array and remove the same value code goes here:
//Create Array
List<int> roleIntList = new List<int>();
foreach(var roles in Phrases){
var roleNode = roles.Value as Phrase;
int roleNum = int.Parse(roleNode.Role);
roleIntList.Add(roleNum);//this can't get value 2,1,1,2,1,2;;
int [] roleInt = roleIntList.Distinct().ToArray();//this not work;
}

Looking at the code labeled // Create Array it looks like you may want to move this line:
int [] roleInt = roleIntList.Distinct().ToArray();
to be outside the foreach loop:
List<int> roleIntList = new List<int>();
foreach(var roles in Phrases){
var roleNode = roles.Value as Phrase;
int roleNum = int.Parse(roleNode.Role);
roleIntList.Add(roleNum);//this can't get value 2,1,1,2,1,2;;
}
int [] roleInt = roleIntList.Distinct().ToArray();//this not work;

First, if you're going to use an XML API then LINQ to XML XDocument is far better to work with than the creaking XmlDocument API.
Second, if you're just trying to get the XML into an object model then XmlSerializer is what you should be looking at. You will have very little code to write in comparison to manually parsing this:
[XmlRoot("Phrases")]
public class Phrases : List<Phrase>
{
}
public class Phrase
{
[XmlAttribute]
public int Role { get; set; }
}
To deserialize your XML:
var serializer = new XmlSerializer(typeof(Phrases));
using (var reader = new StringReader(xml))
{
var phrasesList = (Phrases)serializer.Deserialize(reader);
}
And to get your unique roles:
var uniqueRoles = phrasesList.Select(p => p.Role).Distinct();
I've assumed that your XML has a root node (your code above would throw an exception as it doesn't). For the example, I'm using Phrases, though if you add more information I can change this.

Related

How do I get a specific element in a XML document?

I have a XML file that looks like this:
<Info>
<ID>1</ID>
<Result>
<ID>2</ID>
</Result>
</Info>
I want to count how many Info/Result/ID I have in this file.
I am doing this:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("myFile.xml");
xmlNodeList MyList = xmlDoc.GetElementsByTagName("Info/Result/ID");
int totalCount = MyList.Count;
// other logic...
The method GetElementsByTagName does not find any "ID"-field.
I want to get the "ID = 2".
How do I do that?
To count all the nodes in "Info/Result/ID" path use this..
var count = xmlDoc.SelectNodes("Info/Result/ID")?.Count ?? 0;
To process these nodes
var nodes = xmlDoc.SelectNodes("Info/Result/ID");
foreach (XmlNode node in nodes) {
var idValue = node.InnerText
// do something
}
Got it working, hereĀ“s how:
public static void MyCountExample(string myXml, out int myID)
{
var stream = new MemoryStream(Encoding.UTF8.GetBytes(myXml ?? ""));
var reader = XmlReader.Create(stream);
myID= 0;
reader.IsStartElement("Info");
while (!reader.EOF)
{
if (reader.ReadToFollowing("Result"))
{
if (reader.ReadToDescendant("ID"))
{
myID++;
else
{
return somethingElse();
}
......

Load repeated elements from an XML file

I am looking to load repeated elements from an XML file I have called initialInspections.xml. The problem is that the system needs to be dynamic and to allow as many different inspectionNotes to be added. I need to input all of them even though they have the same name.
If someone could please give me a method of doing this I would be extremely appreciative, since I have been searching for almost 3 hours now and I haven't found anything that works.
I need all off the data from within each inspectionNote node, and it will be put into an array of a structure called initialInspectionNotes.
Here is what I have up to now:
public int propertyID;
public string initialInspectorUsername;
public DateTime intialDateTime;
public struct initialInspectionNotes
{
public string locationWithinProperty;
public string locationExtraNote;
public string costCode;
public float estimatedTime;
}
private void finalInspection_Load(object sender, EventArgs e)
{
//Open the intialInspections xml file and load the values into the form
XmlDocument xdoc = new XmlDocument();
FileStream rFile = new FileStream(values.xmlInitialFileLocation, FileMode.Open);
xdoc.Load(rFile);
XmlNodeList list = xdoc.GetElementsByTagName("initialInspection");
for (int i = 0; i < list.Count; i++)
{
XmlElement initialInspection = (XmlElement)xdoc.GetElementsByTagName("initialInspection")[i];
XmlElement initialInspector = (XmlElement)xdoc.GetElementsByTagName("userInspection")[i];
XmlElement dateTime = (XmlElement)xdoc.GetElementsByTagName("dateTime")[i];
propertyID = int.Parse(initialInspection.GetAttribute("propertyID"));
initialInspectorUsername = initialInspector.InnerText;
intialDateTime = DateTime.Parse(dateTime.InnerText);
}
rFile.Close();
}
The XML looks like this:
<?xml version="1.0" standalone="yes"?>
<initialInspections>
<initialInspection propertyID="1">
<userInspection>defaultadmin</userInspection>
<dateTime>07/11/2015 17:15:20</dateTime>
<inspectionNote>
<location>Dining Room</location>
<locationNote>Remove whole carpet, leave underlay</locationNote>
<CostCode>L1</CostCode>
<estimatedTime>5</estimatedTime>
</inspectionNote>
<inspectionNote>
<location>Other - See Notes</location>
<locationNote>On the marked area with orange spray paint.</locationNote>
<CostCode>B1</CostCode>
<estimatedTime>12</estimatedTime>
</inspectionNote>
</initialInspection>
</initialInspections>
Any help would be much appreciated.
class Note
{
public string Location { get; set; }
public string LocationNote { get; set; }
public string CodeCost { get; set; }
public string EstimatedTime { get; set; }
}
var xml = XElement.Load(...your xml path here );
var data = xml.Descendants("initialInspection").Elements("inspectionNote").Select(n => new Note()
{
Location = n.Element("location").Value,
LocationNote = n.Element("locationNote").Value,
CodeCost = n.Element("CostCode").Value,
EstimatedTime = n.Element("estimatedTime").Value
}).ToList();
One possibility would be to use the LINQ2XML and the LINQ Descendants method to fetch all inspectionNotes at once:
var xml = XDocument.Load(fileLocation); // for example c:\temp\input.xml
// fetch all inspectionNotes
var inspectionNotes = xml.Root.Descendants("inspectionNote").ToList();
// TODO: error handling!
// map inspectionNote node to custom structure
var arrayOfNotes = inspectionNotes.Select (n => new initialInspectionNotes
{
costCode = n.Element("CostCode").Value,
estimatedTime = float.Parse(n.Element("estimatedTime").Value),
locationExtraNote = n.Element("locationNote").Value,
locationWithinProperty = n.Element("location").Value,
})
// and convert the result to array holding elements of the custom structure
.ToArray();
foreach (var note in arrayOfNotes)
{
Console.WriteLine(note.locationExtraNote);
}
The output is:
Remove whole carpet, leave underlay
On the marked area with orange spray paint.
Same logic applies if you want to read and map another XML nodes (f.e. initialInspection).
If you need to use XmlReader then use XPath in order to fetch the inner inspectionNote elements and the values of every inspectionNote element, using XmlNode.SelectSingleNode and XmlNode.SelectNodes:
//Open the intialInspections xml file and load the values into the form
XmlDocument xdoc = new XmlDocument();
FileStream rFile = new FileStream(values.xmlInitialFileLocation, FileMode.Open);
xdoc.Load(rFile);
XmlNodeList list = xdoc.GetElementsByTagName("initialInspection");
// create list of initialInspectionNotes in order to add as many nodes as needed
var notes = new List<initialInspectionNotes>();
// map data
for (int i = 0; i < list.Count; i++)
{
// read data
XmlElement initialInspection = (XmlElement)xdoc.GetElementsByTagName("initialInspection")[i];
XmlElement initialInspector = (XmlElement)xdoc.GetElementsByTagName("userInspection")[i];
XmlElement dateTime = (XmlElement)xdoc.GetElementsByTagName("dateTime")[i];
propertyID = int.Parse(initialInspection.GetAttribute("propertyID"));
initialInspectorUsername = initialInspector.InnerText;
intialDateTime = DateTime.Parse(dateTime.InnerText);
// fetch notes!
var inspectionNotes = initialInspection.SelectNodes("inspectionNote");
foreach (XmlNode inspectionNote in inspectionNotes)
{
// insert data into list
notes.Add(new initialInspectionNotes
{
locationExtraNote = inspectionNote.SelectSingleNode("locationNote").InnerText,
costCode = inspectionNote.SelectSingleNode("CostCode").InnerText,
locationWithinProperty = inspectionNote.SelectSingleNode("location").InnerText
});
}
}
// convert to array if needed
//var arrayOfNotes = notes.ToArray();
rFile.Close();
Regardless of how many inspectionNote elements the XML contains, the list resp. array will read them all.
class InitialInspectionNotes
{
public string Location { get; set; }
public string LocationNote { get; set; }
public string CodeCost { get; set; }
public string EstimatedTime { get; set; }
}
var xdoc = XDocument.Load("yourpath\filename.xml");
var dataXml = xdoc.Descendants("initialInspection").Elements("inspectionNote").Select(n => new InitialInspectionNotes()
{
Location = n.Element("location").Value,
LocationNote = n.Element("locationNote").Value,
CodeCost = n.Element("CostCode").Value,
EstimatedTime = n.Element("estimatedTime").Value
}).ToList();
var xmlList = new List<object>();
for (int i = 0; i < dataXml.Count; i++)
{
xmlList.Add(dataXml[i]);
}
Despite all the answers above might have worked, I have however found it quite complicated for reading just elements. I found a simpler solution which I would like to share for future audience in this case.
Supposing you have read the document stream into XmlDocument object named as document.
var dataNodes = document.GetElementsByTagName("Data");
var toList = dataNodes.OfType<XmlElement>().ToList();
In my case, Data node was not being called repeatedly. Hence this works, now I was able to append multiple nodes with the same name.

XML to String List

I have some code that I need to put into a string list in C# and I am reading this code from an XML files and the layout of it is something like below...
<?xml version="1.0"?>
<accountlist>
<main>
<account id="1" special_id="4923959">
<username>Adam</username>
<motto>Hello Everyone>
<money>1004</money>
<friends>394</friends>
<rareid>9</rareid>
<mission>10</mission>
</account>
</main>
</accountlist>
How can I put each account tag into a string list? from the first < account > to the < / account > tag?
Please do NOT tell me to go to the link below as it does NOT work!!
How to read a XML file and write into List<>?
So far I have tried the below code, and the string list just stays empty
XDocument doc = XDocument.Parse(this._accountsFile);
List<string> list = doc.Root.Elements("account")
.Select(element => element.Value)
.ToList();
this._accounts = list;
You'll have to use Descendants instead of Elements:
List<string> list = doc.Root.Descendants("account").Descendants()
.Select(element => element.Value)
.ToList();
Elements only returns child elements of the element (in case of the root element this means <main>).
Descendants returns the entire tree inside the element.
Also: You'll have to fix the tag <motto>Hello Everyone> to <motto>Hello Everyone</motto>
This will work on your example (but you need to close this tag <motto>Hello Everyone>
public List<string> GetAccountsAsXmlList(string filePath)
{
XmlDocument x = new XmlDocument();
x.Load(filePath);
List<string> result = new List<string>();
XmlNode currentNode;
foreach (var accountNode in x.LastChild.FirstChild.ChildNodes)
{
currentNode = accountNode as XmlNode;
result.Add(currentNode.InnerXml);
}
return result;
}
EDIT as an answer to your question:
Is there a way I can get the id and specal_id in a seperate string?
you can use currentNode.Attributes["YourAttributeName"].Value, to get the values.
assume you have class Account :
class Account
{
public string accountXml { get; set; }
public string Id { get; set; }
public string Special_id { get; set; }
}
Then :
public List<Account> GetAccountsAsXmlList(string filePath)
{
XmlDocument x = new XmlDocument();
x.Load(filePath);
List<Account> result = new List<Account>();
XmlNode currentNode;
foreach (var accountNode in x.LastChild.FirstChild.ChildNodes)
{
currentNode = accountNode as XmlNode;
result.Add(new Account
{
accountXml = currentNode.InnerXml,
Id = currentNode.Attributes["id"].Value,
Special_id = currentNode.Attributes["special_id"].Value,
});
}
return result;
}
Use XPath to get the account element first:
using System.Xml.XPath;
XDocument doc = XDocument.Parse(xml);
foreach(var account in doc.XPathSelectElements("accountlist/main/account")){
List<string> list = account.Descendants()
.Select(element => element.Value)
.ToList();
}
Try this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication37
{
class Program
{
static void Main(string[] args)
{
string input =
"<?xml version=\"1.0\"?>" +
"<accountlist>" +
"<main>" +
"<account id=\"1\" special_id=\"4923959\">" +
"<username>Adam</username>" +
"<motto>" +
"Hello Everyone>" +
"<money>1004</money>" +
"<friends>394</friends>" +
"<rareid>9</rareid>" +
"<mission>10</mission>" +
"</motto>" +
"</account>" +
"</main>" +
"</accountlist>";
XDocument doc = XDocument.Parse(input);
var results = doc.Descendants("accountlist").Select(x => new {
id = x.Element("main").Element("account").Attribute("id").Value,
special_id = x.Element("main").Element("account").Attribute("special_id").Value,
username = x.Element("main").Element("account").Element("username").Value,
motto = x.Element("main").Element("account").Element("motto").FirstNode.ToString(),
money = x.Element("main").Element("account").Element("motto").Element("money").Value,
friends = x.Element("main").Element("account").Element("motto").Element("friends").Value,
rareid = x.Element("main").Element("account").Element("motto").Element("rareid").Value,
mission = x.Element("main").Element("account").Element("motto").Element("mission").Value,
}).ToList();
}
}
}

Get var from Other file in c# [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I get 3 files, I want to use the variable values from each other, one file is :
public class Dialogs
{
public Dictionary<string, Phrase> Phrases = new Dictionary<string, Phrase>();
}
public class Phrase
{
public string PhraseID = null;
public string Role = null;
}
the second one goes here:
public class DiaLoader
{
public Dialogs LoadDialog()
{
// Variables
List<Phrase> phrasesList = new List<Phrase>();
Dialogs resultDialog = new Dialogs();
XmlDocument doc = new XmlDocument();
doc.LoadXml("<Phrase Role="2"></Phrase>
<Phrase Role="2"></Phrase>
<Phrase Role="1"></Phrase>
<Phrase Role="1"></Phrase>
<Phrase Role="2"></Phrase>
<Phrase Role="1"></Phrase>
<Phrase Role="2"></Phrase>");
//get all the phrases
XmlNodeList phrases = xml.GetElementsByTagName("Phrase");
foreach (XmlNode phraseNode in phrases)
{
Phrase phrase = NodeToPhrase(phraseNode);
phrasesList.Add(phrase);
}
//Phrase node to phrase
private Phrase NodeToPhrase(XmlNode node)
{
Phrase phrase = new Phrase();
XmlNode roleNode = node.Attributes["Role"];
if (roleNode != null && !string.IsNullOrEmpty(roleNode.Value))
phrase.Role = roleNode.Value;
return phrase;
}
}
as you can see, i give the the string Role value using xml in the second file,, and the third one, I want to create var and get the value of Role, how can I do it? My code goes here:
DiaLoader dia= new DiaLoader();
public void Export(dia.LoadDialog()) {
XmlDocument doc = new XmlDocument();
string myVar = Phrase.Role;//this can't the value of role
}
I see in your example you have some phrases in a xml file, something like:
<Phrases>
<Phrase Role="2">Example 1</Phrase>
<Phrase Role="2">Example 2</Phrase>
<Phrase Role="1">Example 3</Phrase>
<Phrase Role="1">Example 4</Phrase>
<Phrase Role="2">Example 5</Phrase>
<Phrase Role="1">Example 6</Phrase>
<Phrase Role="2">Example 7</Phrase>
</Phrases>
And you want to read all these phrases into a dictionary, and later retrieve the text for certain role.
So, I modified a bit your code to allow to compile.
using System.Collections.Generic;
using System.Linq;
using System.Xml;
namespace Test001
{
public class Dialogs
{
private static string DEFAULT_DATA =
"<Phrases>" +
"<Phrase Role=\"2\">Example 1</Phrase>" +
"<Phrase Role=\"2\">Example 2</Phrase>" +
"<Phrase Role=\"1\">Example 3</Phrase>" +
"<Phrase Role=\"1\">Example 4</Phrase>" +
"<Phrase Role=\"2\">Example 5</Phrase>" +
"<Phrase Role=\"1\">Example 6</Phrase>" +
"<Phrase Role=\"2\">Example 7</Phrase>" +
"</Phrases>"
;
private int nextID;
private Dictionary<string, Phrase> Phrases = new Dictionary<string, Phrase>();
public List<Phrase> PhrasesList
{
get
{
return this.Phrases.Values.ToList();
}
}
public Dialogs()
{
this.Phrases = new Dictionary<string, Phrase>();
this.nextID = 0;
}
public bool Load(string filename = null)
{
this.Phrases.Clear();
this.nextID = 0;
XmlDocument doc = new XmlDocument();
try
{
if (filename == null)
{
doc.LoadXml(DEFAULT_DATA);
}
else
{
doc.Load(filename);
}
}
catch
{
// Error loading data
return false;
}
// Get all the phrases
XmlNodeList phrases = doc.GetElementsByTagName("Phrase");
foreach (XmlNode phraseNode in phrases)
{
Phrase phrase = NodeToPhrase(phraseNode);
this.Add(phrase);
}
return true;
}
public void Add(Phrase phrase)
{
this.Phrases.Add(this.nextID.ToString(), phrase);
this.nextID++;
}
// Parse a xml node to a phrase
private Phrase NodeToPhrase(XmlNode node)
{
Phrase phrase = new Phrase();
XmlNode roleNode = node.Attributes["Role"];
if (roleNode != null && !string.IsNullOrEmpty(roleNode.Value))
{
phrase.Role = roleNode.Value;
phrase.PhraseID = this.nextID.ToString();
if (node.HasChildNodes)
{
phrase.Text = node.FirstChild.Value;
}
this.nextID++;
}
return phrase;
}
}
}
I left unchanged the class Phrase, except added a new field to store the text
public class Phrase
{
public string PhraseID = null;
public string Role = null;
public string Text = null;
}
And for the usage, it would be something like this:
Dialogs dia = new Dialogs();
// dia.Load("full_path_to_your_nice_xml_file.xml")
dia.Load(); // Load default xml data just for testing purposes
var myVar = dia.PhrasesList.Find(phrase => phrase.Role == "2").Text;

randomly Select XML nodes with same names

I have this XML file:
<Main>
<QA>
<question>What is your favorite color?</question>
<!--pick random!-->
<answer>Blue</answer>
<answer>Red</answer>
<answer>Green</answer>
<answer>Yellow</answer>
</QA>
<QA>
<question>What is your favorite programming language?</question>
<!--pick random!-->
<answer>PHP</answer>
<answer>C#</answer>
<answer>Java</answer>
<answer>VB.Net</answer>
</QA>
I want when the user enter one of the question that specified in above xml file, program pick a random answer from nodes.
For example when user enters "What is your favorite programming language?" in TextBox,
program must generate PHP,C#,Java or VB.Net randomly.
this is my code but not correct:
XmlDocument xml = new XmlDocument();
xml.Load("QA.xml");
XmlNodeList xList = xml.SelectNodes("Main/QA");
foreach (XmlNode xn in xList)
{
string Question = xn["question"].InnerText;
if (Question == txtQuestion.Text)
{
XmlNodeList answerlist = xml.SelectNodes("Main/QA/answer");
foreach (XmlNode ans in answerlist)
{
Console.WriteLine(ans.InnerText);
}
}
}
Output:
Blue
Red
Green
Yellow
PHP
C#
Java
VB.Net
Please help.
Try this:
XmlDocument xml = new XmlDocument();
xml.Load("QA.xml");
XmlNodeList xList = xml.SelectNodes("Main/QA");
foreach (XmlNode xn in xList)
{
string Question = xn["question"].InnerText;
if (Question == txtQuestion.Text)
{
XmlNodeList answerlist = xn.SelectNodes("./answer");
foreach (XmlNode ans in answerlist
.Cast<XmlNode>()
.OrderBy(elem => Guid.NewGuid()))
{
Console.WriteLine(ans.InnerText);
}
}
}
using Linq To Xml,
Random rnd = new Random();
var xDoc = XDocument.Load("QA.xml");
var question = xDoc.Descendants("QA")
.First(d => d.Element("question").Value == txtQ.Text);
var answer = question.Elements()
.Skip(rnd.Next(0, question.Elements().Count()))
.First().Value;

Categories

Resources