The Input XML Format is
<FileDetails>
<Date FileModified="28/06/2010 10:43:36" />
<Data Name="DIG" List="U16,R30" Level="2"/>
<Data Name="DIG1" List="Uee,Ree" Level="2"/>
<Data Name="DIG2" List="Udd,Rdd" Level="2"/>
<Data Name="N234" List="J3" Level="2"/>
<Data Name="N11" List="U2" Level="1"/>
<Data Name="N12" List="U219" Level="1"/>
<Data Name="N13" List="U218" Level="1"/>
<Data Name="N14" List="U243" Level="1"/>
<Data Name="N15" List="U142" Level="0"/>
<Data Name="N16" List="U119" Level="0"/>
<Data Name="N17" List="U118" Level="0"/>
<Data Name="N18" List="U143" Level="0"/>
</FileDetails>
Read the above XML based Up on the Attribute : "Level".
Data Structure:
Dictionary<int,string> l_dicttLevel1 = new Dictionary<int,string>();
Dictionary<int,List<string>> l_dicttLevel2 = new Dictionary<int,List<string>>();
Dictionary<int,string> l_dicttLevel0 = new Dictionary<int,string>();
Output:
For l_dicttLevel1 :
l_dictLevel1[1] = "U2"
l_dictLevel1[2] = "U219"
l_dictLevel1[3] = "U218"
l_dictLevel1[4] = "U243"
For l_dicttLevel0 :
l_dictLevel0[1] = "U142"
l_dictLevel0[2] = "U119"
l_dictLevel0[3] = "U118"
l_dictLevel0[4] = "U143"
For l_dicttLevel2 :
Here i ll seperate the values(i.e)List<string> of Dictionary(l_dicttLevel2 ) by using Comma.
l_dictLevel2[1] = "U16","R30"
l_dictLevel2[2] = "Uee","Ree"
l_dictLevel2[3] = "Udd","Rdd"
Here is my Code :
XmlDocument xDoc = new XmlDocument();
xDoc.Load(l_strPath);
XmlElement Root = xDoc.DocumentElement;
int l_nCount = 0;
l_dicttLevel1 = (from XmlNode l_nNode in Root.SelectNodes("//Data")
where l_nNode.Attributes["Level"].Value == "1"
select new
{
Key = l_nCount++,
Value = l_nNode.Attributes["List"].Value
}).ToDictionary(l_strTemp => Convert.ToInt32(l_strTemp.Key), l_strTemp => l_strTemp.Value);
l_dicttLevel2 = (from XmlNode l_nNode in Root.SelectNodes("//Data")
where l_nNode.Attributes["Level"].Value == "0"
select new
{
Key = l_nCount++,
Value = l_nNode.Attributes["List"].Value
}).ToDictionary(l_strTemp => Convert.ToInt32(l_strTemp.Key), l_strTemp => l_strTemp.Value);
l_dicttLevel2= (from XmlNode l_nNode in Root.SelectNodes("//Data")
where l_nNode.Attributes["Level"].Value == "2"
select new
{
Key = l_nCount++,
Value = l_nNode.Attributes["List"].Value
}).ToDictionary(l_strTemp => Convert.ToInt32(l_strTemp.Key),
l_strTemp => l_strTemp.Value.Split(',').ToList());
xDoc = null;
Is it possible Using LINQ? . Please let me know if u have any queries.
Try this
XDocument XDOC = XDocument.Load(Application.StartupPath + "\\Test.xml");
dictLevel1 = XDOC.Descendants("Data").Where(x => (Int32)x.Attribute("Level") == 1)
.Select((a, b) => new { Index=b, Element=a})
.ToDictionary(x => x.Index+1,x=>x.Element.Attribute("List").Value );
dictLevel0 = XDOC.Descendants("Data").Where(x => (Int32)x.Attribute("Level") == 0)
.Select((a, b) => new { Index = b, Element = a })
.ToDictionary(x => x.Index + 1, x => x.Element.Attribute("List").Value);
dictLevel2 = XDOC.Descendants("Data").Where(x => (Int32)x.Attribute("Level") == 2)
.Select((a, b) => new { Index = b, Element = a })
.ToDictionary(x => x.Index + 1, x => x.Element.Attribute("List").Value.Split(',').ToList());
Related
void Main()
{
string xml = #"<root>
<Page1>
<Key_Head>Name1</Key_Head>
<Key_Title>value1</Key_Title>
</Page1>
<Page1>
<Key_Head>Name2</Key_Head>
<Key_Title>value2</Key_Title>
</Page1>
</root>";
var doc1 = XDocument.Parse(xml);
var result = ConvertXmlToDic(doc1.Root);
}
private static List<NameValuePair> ConvertXmlToDic(XElement element)
{
var result =
element
.Elements()
.Select(e => new
{
Name = e.Name.ToString(),
Value = (e.Descendants().Count() == 0)
? e.Value
: ConvertXmlToDic(e).ToString()
})
.ToDictionary(e => e.Name, e => e.Value)
.Select(e => new List<NameValuePair>()
{
new NameValuePair() { Name = e.Key, Value = e.Value }
});
return (List<NameValuePair>)result;
}
How do I get the tag values for <Key_Head>Name1</Key_Head><Key_Title>value1</Key_Title> as key values. Like list of (Name1,Value1) ? This is what I have tried so far.
You can simplify the logic to retrieve Key_Head and Key_Title as below:
private static List<NameValuePair> ConvertXmlToDic(XElement element)
{
var result = element.Elements()
.Select(e => new NameValuePair
{
Name = e.Element("Key_Head").Value,
Value = e.Element("Key_Title").Value
})
.ToList();
return result;
}
Output
Name: Name1, Value: value1
Name: name2, Value: value2
Sample program
I'm taking XML, filtering and putting it into a combobox, and my issue is taking the selected combobox entry, and saving each individual piece. Here is some sample XML im using.
<SolutionString>
<Solutions>
<Solution>
<ID>1</ID>
<Property>
<Name>DriverSheave</Name>
<Value>1VP34</Value>
</Property>
<Property>
<Name>DriverBushing</Name>
<Value>
</Value>
</Property>
<Property>
<Name>DrivenSheave</Name>
<Value>AK49</Value>
</Property>
<Property>
<Name>DrivenBushing</Name>
<Value>
</Value>
</Property>
</Solution>
<Solution>
<ID>2</ID>
...ect(ID 2, ID 3 and so on). After this im sticking these XML results into my combobox like this.
XmlDocument doc1 = new XmlDocument();
doc1.LoadXml(XmlString.ToString());
PTS.Library.VbeltDriveLibrary.Configurator Configurator = new PTS.Library.VbeltDriveLibrary.Configurator(doc1);
if (Configurator.SolveAndValidate())
{
var solutions = Configurator.Results.ToXDocument();
int i = 0;
var indexesToChoose = new List<int> { 9, 8, 4, 5, 0, 2, 7, 6 };
var cat = solutions
.Descendants("Solution")
.Select(x => new
{
ID = (string)x.Element("ID"),
Properties = x.Elements("Property").Select(p => new
{
Name = (string) p.Element("Name"),
Value = (string) p.Element("Value"),
idx = (i < 11 ? i++ : i = 0)
})
.Where(y => indexesToChoose.Contains(y.idx))
.OrderBy(z => indexesToChoose.FindIndex(p => p == z.idx))
.ToList()
});
var items = cat
.Select(s => new
{
ID = s.ID,
Text = string.Format("{0}. {1}", s.ID,
string.Join(", ", s.Properties
.Select(p => string.Format("{0} = {1}",
p.Name,
p.Value ?? "(null)"))))
}).ToArray();
comboBox1.DisplayMember = "Text";
comboBox1.ValueMember = "ID";
comboBox1.Items.AddRange(items);
Finally, i want to be able to take this selection,(this is the selected items in the combobox)
Cost = 1072.93, ActualDrivenShaftSpeed = 900/1073, Belt = B84, BeltQty = 5, DriverSheave = 5MVP70B84P, Comment2 = Correct tension for this drive (1.31 lb. should deflect belt 0.48 in.) will have 30 lb. 'running' Hub Load, DrivenSheave = 5MVB70R, ActualServiceFactor = 40.63, ActualCenterDistance = 30.8
and filter each piece out into a variable, for example,
string ActualCenterDistance = 30.8
Obviously i can put the whole selection into a string easily with a simple combobox.selectedText, however putting each piece into individual strings (or any other var) is my issue.
It looks like a bad design for me.
Consider instead of using anonymous type here:
.Select(x => new
{
ID = (string)x.Element("ID"),
Properties = x.Elements("Property").Select(p => new
just create instance of your own class which could be like:
public class MyItem
{
public string ID;
public List<Tuple<string, string>> Properties;
public string GetProperty(string name)
{
if (Properties == null)
return null;
var item = Properties.FirstOrDefault(x => x.Item1 == name);
return item == null ? null : item.Item2;
}
public override string ToString()
{
return string.Join(", ", Properties
.Select(p => string.Format("{0} = {1}",
p.Item1,
p.Item2 ?? "(null)")));
}
}
in this case (since I've transferred logic of concatenation Name/Value of properties to ToString method override of MyItem class) - you can fill combobox with items having type of MyItem, and you will be able to access all your data easily like:
var item = comboBox1.SelectedItem as MyItem;
string x = item.GetProperty("DriverSheave");
Changes to be made with the code:
var items = solutions.Descendants("Solution")
.Select(x => new MyItem
{
ID = (string)x.Element("ID"),
Properties = x.Elements("Property").Select(p => new
{
Name = (string)p.Element("Name"),
Value = (string)p.Element("Value"),
idx = (i < 11 ? i++ : i = 0)
})
.Where(y => indexesToChoose.Contains(y.idx))
.OrderBy(z => indexesToChoose.FindIndex(p => p == z.idx))
.Select(z => new Tuple<string, string>(z.Name, z.Value))
.ToList()
}).ToArray();
comboBox1.DisplayMember = "Text";
comboBox1.ValueMember = "ID";
comboBox1.Items.AddRange(items);
Note: this is essentially important to have some custom class as Item for combobox, because in the case of anonymous type being used you will not be able to access its fields when taking object from combobox.SelectedItem.
I cannot open the following page. Last row problem. I don't want bottom row. How can i do.
HtmlWeb web = new HtmlWeb();
web.OverrideEncoding = Encoding.GetEncoding("windows-1254");
HtmlAgilityPack.HtmlDocument doc = web.Load("http://www.yerelnet.org.tr/ilceler/ilce.php?ilceid=198191");
var ilceNufus = doc.DocumentNode
.SelectNodes("//*[#id='Table_01']/tr[2]/td[1]/table/tr/td/table[5]/tr/td[2]/table[1]/tr/td[3]/table[2]/tr")
.Skip(1)
.Select(td => td.Elements("td").Select(row => row.InnerText).ToList())
.Select(td => new { Yil = td[0], Toplam = td[1], Sehir = td[2], Koy = td[3] })
.ToList();
dataGridView1.DataSource = ilceNufus;
Just add a Where
var ilceNufus = doc.DocumentNode.SelectNodes("//*[#id='Table_01']/tr[2]/td[1]/table/tr/td/table[5]/tr/td[2]/table[1]/tr/td[3]/table[2]/tr")
.Skip(1)
.Select(td => td.Elements("td").Select(row => row.InnerText).ToList())
.Where(tds => tds.Count == 4)
.Select(td => new { Yil = td[0], Toplam = td[1], Sehir = td[2], Koy = td[3] }).ToList();
How would I go about getting the ID information using Linq. I'm trying to add them to an array of int.
<FactionAttributes>
<name>Player</name>
<id>0</id>
<relationModifier>1</relationModifier>
<relations>
<id0>100</id0>
<id1>50</id1>
<id2>50</id2>
<id3>50</id3>
<id4>50</id4>
<id5>50</id5>
</relations>
</FactionAttributes>
That is my XML.
Here is the code I'm using so far.
void InitFactions()
{
int count = 0;
string filepath = Application.dataPath + "/Resources/factiondata.xml";
XDocument factionXML = XDocument.Load(filepath);
var factionNames = from factionName in factionXML.Root.Elements("FactionAttributes")
select new {
factionName_XML = (string)factionName.Element("name"),
factionID_XML = (int)factionName.Element("id"),
factionRelations_XML = factionName.Element("relations")// Need to turn this into array.
};
foreach ( var factionName in factionNames)
++count;
foreach ( var factionName in factionNames)
{
Factions f = new Factions();
f.otherFactionsName = new string[count];
f.otherFactionsRelation = new int[count];
int others = 0;
f.FactionName = factionName.factionName_XML;
Debug.Log(factionName.factionRelations_XML);
// Adds Rivals, not self to other list.
foreach (var factionName2 in factionNames)
{
if (factionName.factionID_XML == factionName2.factionID_XML)
continue;
f.otherFactionsName[(int)factionName2.factionID_XML] = factionName2.factionName_XML;
// THIS IS WHERE IM ADDING THE RELATIONS IN //
f.otherFactionsRelation[(int)factionName2.factionID_XML] = factionName.factionRelations_XML[(int)factionName2.factionID_XML];
Debug.Log(f.FactionName + " adds: " + factionName2.factionName_XML);
++others;
}
}
}
I have made multiple attempts using nodes and what not. I can't seem to figure out the correct syntax.
XDocument doc = XDocument.Load(Path);
//To get <id>
var MyIds = doc.Element("FactionAttributes").Element("id").Value;
//To get <id0>, <id1>, etc.
var result = doc.Element("FactionAttributes")
.Element("relations")
.Elements()
.Where(E => E.Name.ToString().Contains("id"))
.Select(E => new { IdName = E.Name, Value = E.Value});
If you want array of ints replace the select with this
.Select(E => Convert.ToInt32(E.Value)).ToArray();
If you are just after the relations Ids use this simple query
var doc = XDocument.Load("c:\\tmp\\test.xml");
var ids = doc.Descendants("relations").Elements().Select(x => x.Value);
If you want the Id and the relations ids in one array use this
var id = doc.Descendants("id").Select(x=>x.Value).Concat(doc.Descendants("relations").Elements().Select(x => x.Value));
I have a three List in c# ,the variable names are l_lstData1,l_lstData2,l_lstData3
The File Structure is
<FileDetails>
<Date FileModified="29/04/2010 12:34:02" />
<Data Name="Data_1" DataList="India" Level="2" />
<Data Name="Data_2" DataList="chennai" Level="2" />
<Data Name="Data_3" DataList="hyderabad" Level="2" />
<Data Name="Data_4" DataList="calcutta" Level="2" />
<Data Name="Data_5" DataList="vijayawada" Level="1" />
<Data Name="Data_6" DataList="cochin" Level="1" />
<Data Name="Data_7" DataList="madurai" Level="0" />
<Data Name="Data_8" DataList="trichy" Level="0" />
</FileDetails>
The Values od 3 Lists are as follows :
l_lstData1[0] = "India";l_lstData1[1] = "chennai";l_lstData1[2] = "hyderabad";
l_lstData1[3] = "calcutta";
so the level attribute of the above XML(element : Data) has tha value = "2".
l_lstData2[0] = "vijayawada";l_lstData2[1] = "cochin";
so the level attribute of the above XML(element : Data) has tha value = "1".
l_lstData3[0] = "madurai";l_lstData3[1] = "trichy";
so the level attribute of the above XML(element : Data) has tha value = "0".
How can i create the XML using Xdocument and also using LINQ....Plz revert back me if u have any queries
Here's an alternative to Pramodh's solution, if I've understood it correctly:
// First build up a single list to work with, using an anonymous type
var singleList = l_lstData1.Select(x => new { Value = x, Level = 2})
.Concat(l_lstData2.Select(x => new { Value = x, Level = 1})
.Concat(l_lstData3.Select(x => new { Value = x, Level = 0});
var doc = new XDocument(
new XElement("FileDetails",
new XElement("Date",new XAttribute("FileModified", DateTime.Now)),
singleList.Select((item, index) => new XElement("Data",
new XAttribute("Name", "Data_" + (index + 1)),
new XAttribute("DataList", item.Value),
new XAttribute("Level", item.Level))));
Try like this:
XDocument TEMP = new XDocument(new XElement("FileDetails",
new XElement("Date",new XAttribute("FileModified", DateTime.Now.ToString())),
l_lstData1.Select(l => new XElement("Data",new XAttribute("Name","Data_"+(l_lstData1.IndexOf(l)+1).ToString()),
new XAttribute ("DataList",l.ToString()),
new XAttribute ("Level","Level2"))),
l_lstData2.Select(l => new XElement("Data",new XAttribute("Name","Data_"+(l_lstData2.Count + l_lstData2.IndexOf(l)+1).ToString()),
new XAttribute ("DataList",l.ToString()),
new XAttribute ("Level","Level1"))) ,
l_lstData3.Select(l => new XElement("Data",new XAttribute("Name", "Data_" + (l_lstData3.Count + l_lstData2.Count + l_lstData3.IndexOf(l) + 1).ToString()),
new XAttribute ("DataList",l.ToString()),
new XAttribute ("Level","Level0")))
));
TEMP.Save("TEMP.xml");