Add children to XElement via LINQ - c#

I have a Collection of a class that looks like:
public class Group
{
public string Name { get; set; }
}
private ObservableCollection<Group> _groups;
now I want to create a xml structure from groups that looks like:
<Ou>
<Group>AAA</Group>
<Group>BBB</Group>
<Group>CCC</Group>
<Group>DDD</Group>
</Ou>
I have try following:
new XElement("Ou", //How continue here?)
but do not know how to continue coding.

Like this:
var element =
new XElement(
"Ou",
new XElement("Group", "AAA"),
new XElement("Group", "BBB"),
new XElement("Group", "CCC"),
new XElement("Group", "DDD"));
Or from your data structure:
var element =
new XElement("Ou",
from g in _groups
select new XElement("Group", g.Name));

new XElement("Ou", _groups.Select(g => new XElement("Group", g.Name)));

You can try following code:
var element = new XElement("Ou");
element.Add(new XElement("Group", "AAA"));
element.Add(new XElement("Group", "BBB"));
element.Add(new XElement("Group", "CCC"));
element.Add(new XElement("Group", "DDD"));
...

Related

C#: How to iterate trough own Dictionary to write XElements in my XDocument?

I got a dictionary with different propertys. Now I want to create a XML File out of this dictionary, but I dont know how I can iterate trough each entry in my dictionary.
In my dictionary there are 2 propertys called quantity and price.
So this is actually what my code looks like.
XDocument xDoc = new XDocument(
new XElement("itemlist",
new XElement("item",
new XAttribute("article", "1"),
new XAttribute("quantity", "150"),
new XAttribute("price", "20"))));
xDoc.Save("C:/Users/User/Desktop/XMLOutput.xml");
But I don't want to write every entry in my dictionary myself, so I'm looking for a solution something like this:
XDocument xDoc = new XDocument(
new XElement("itemlist",
foreach (KeyValuePair<string, item> it in dictionary_items)
{
new XElement("item",
new XAttribute("article", it.Key),
new XAttribute("quantity", it.Value.quantity),
new XAttribute("price", it.Value.price)
));
}
xDoc.Save("C:/Users/User/Desktop/XMLOutput.xml");
So I want to iterate trough each entry in my dictionary and write it as above in my XML-File. How can I do that?
Thanks for your help.
Sure. You can use XStreamingElement for this:
using System;
using System.Collections.Generic;
using System.Xml.Linq;
using System.Linq;
namespace ConsoleApp31
{
class Program
{
class Item
{
public int quantity { get; set; }
public double price { get; set; }
}
static void Main(string[] args)
{
var dictionary_items = new Dictionary<string, Item>();
dictionary_items.Add("abc", new Item() { quantity = 1, price = 3.3 });
dictionary_items.Add("def", new Item() { quantity = 1, price = 3.3 });
XDocument xDoc = new XDocument(
new XStreamingElement("itemlist",
from it in dictionary_items
select new XElement("item",
new XAttribute("article", it.Key),
new XAttribute("quantity", it.Value.quantity),
new XAttribute("price", it.Value.price)))
);
Console.WriteLine(xDoc.ToString());
Console.ReadKey();
}
}
}
outputs
<itemlist>
<item article="abc" quantity="1" price="3.3" />
<item article="def" quantity="1" price="3.3" />
</itemlist>
var list = new XElement("itemlist");
foreach (KeyValuePair<string, item> it in dictionary_items)
{
list.Add(new XElement("item",
new XAttribute("article", it.Key),
new XAttribute("quantity", it.Value.quantity),
new XAttribute("price", it.Value.price)
)));
}
XDocument xDoc = new XDocument(list);
xDoc.Save("C:/Users/User/Desktop/XMLOutput.xml");

Missing the begin of the root in xml

The Code:
new XElement("Person"));
XElement items = xdoc.Root
foreach (ObservableCollection<Person> x in list)
{
XElement children = new XElement("List");
foreach (var person in x)
{
XElement person = new XElement("Person",
new XElement("Name", person.name),
new XElement("Surname", person.surn),
new XElement("City", person.city));
items.Add(person);
}
items.Add(children);
}
xdoc.Save(path);
But in XML it looks like that:
<Pepole>
<Person>
<name>d</name>
<surname>a</surname>
<city>b</city>
</Person>
**<List />**
It's missing the start of the list - please any advice how to solve it?
Its very unclear what you want. You have a collection of lists of Person objects. Do you want a separate List tag for each List or all the Person tags to be within one List tag?
Well here's both:
All in one list:
XElement items = xdoc.Root
XElement bigList= new XElement("List");
items.Add(bigList);
foreach (ObservableCollection<Person> x in list)
{
foreach (var person in x)
{
XElement person = new XElement("Person",
new XElement("Name", person.name),
new XElement("Surname", person.surn),
new XElement("City", person.city));
bigList.Add(person);
}
}
xdoc.Save(path);
Individual list for each List:
XElement items = xdoc.Root
foreach (ObservableCollection<Person> x in list)
{
XElement smallList= new XElement("List");
items.Add(smallList);
foreach (var person in x)
{
XElement person = new XElement("Person",
new XElement("Name", person.name),
new XElement("Surname", person.surn),
new XElement("City", person.city));
smallList.Add(person);
}
}
xdoc.Save(path);
It's missing the start of the list
No - it's rendering an empty List tag . You added person to the root element instead of to the children element, so it gets rendered under the root instead of under List.

How to add list, with LINQ, in an xml?

I have the following structure in an xml:
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfNO xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<No>
<Id>1</Id>
<Name>txt_1</Name>
<Text>some text</Text>
<Txt_relacionados>
<string>txt_4</string>
<string>txt_4</string>
<string>txt_4</string>
</Txt_relacionados>
<N>0</N>
<X>285</X>
<Y>31</Y>
<Externa>false</Externa>
<EM>false</EM>
<B>false</B>
<K>false</K>
<L1>false</L1>
<L2>false</L2>
<L3>false</L3>
<L4>false</L4>
<L5>false</L5>
<L6>false</L6>
<L7>false</L7>
<L8>false</L8>
<L9>false</L9>
<L10>false</L10>
<L11>false</L11>
<L12>false</L12>
<IP>0</IP>
</No>
I'm having trouble inserting the "Txt_relacionados" element because it contains a list of strings.
In the VO of this element i have the following:
[XmlArray("Txt_relacionados"), XmlArrayItem("string", Type = typeof(String))]
private List<String> txt_relacionados = new List<String>();
public List<String> Txt_relacionados
{
get { return txt_relacionados; }
set { txt_relacionados = value; }
}
What changes should I make in the code below to be able to insert this list?
public void inserir2(VoNo value)
{
RefreshXDoc();
XElement no = XElement.Load(path);
XElement element = new XElement("No",
new XElement("Id", value.Id),
new XElement("Name", value.Name),
new XElement("Text", value.Text),
new XmlArrayAttribute("Txt_relacionados", value.Txt_relacionados),
new XElement("N", value.N),
new XElement("X", value.X),
new XElement("Y", value.Y),
new XElement("Externa", value.Externa),
new XElement("B", value.B),
new XElement("K", value.K),
new XElement("L1", value.L1),
new XElement("L2", value.L2),
new XElement("L3", value.L3),
new XElement("L4", value.L4),
new XElement("L5", value.L5),
new XElement("L6", value.L6),
new XElement("L7", value.L7),
new XElement("L8", value.L8),
new XElement("L9", value.L9),
new XElement("L10", value.L10),
new XElement("L11", value.L11),
new XElement("L12", value.L12),
new XElement("IP", value.IP));
no.Add(element);
no.Save(path);
}
Thanks!!
You need to create Txt_relacionados element before you create new element No and then pass Txt_relacionados at proper place when you are creating No.
Consider following.
public void inserir2(VoNo value)
{
var rels = new XElement("Txt_relacionados");
foreach (var x in value.Txt_relacionados)
{
var elem = new XElement("string", x);
rels.Add(elem);
}
RefreshXDoc();
XElement no = XElement.Load(path);
XElement element = new XElement("No",
new XElement("Id", value.Id),
new XElement("Name", value.Name),
new XElement("Text", value.Text),
rels,
new XElement("N", value.N),
new XElement("X", value.X),
new XElement("Y", value.Y),
new XElement("Externa", value.Externa),
new XElement("B", value.B),
new XElement("K", value.K),
new XElement("L1", value.L1),
new XElement("L2", value.L2),
new XElement("L3", value.L3),
new XElement("L4", value.L4),
new XElement("L5", value.L5),
new XElement("L6", value.L6),
new XElement("L7", value.L7),
new XElement("L8", value.L8),
new XElement("L9", value.L9),
new XElement("L10", value.L10),
new XElement("L11", value.L11),
new XElement("L12", value.L12),
new XElement("IP", value.IP));
no.Add(element);
no.Save(path);
}

Add collection of items( xml elements) to XML doc

How to add the collection of items to XML Document ? Something I started trying, but it's wrong! I'll be grateful for the link on the Internet at a good tutorial too. Also, It is assumed that the iteration will be some elements.
Such code:
public static void Create_Interfaces()
{
XDocument Interfaces;
Interfaces = XDocument.Load("Interfaces.xml");
List<string> intf = new List<string>{"em0","em1","em2"};
foreach (var i in intf)
{
Interfaces = new XDocument(
new XElement("Interfaces",
new XElement("Interface",
new XElement("name", i),
new XElement("vlan-tagging", XElement.EmptySequence),
new XElement("unit",
new XElement("vlan-id", "10"),
new XElement("family", new XElement("inet", new XElement("address", new XElement("name", "10.10.1.23/24"))))))));
}
Interfaces.Save("Interfaces.xml");
}
Get your root element add new elements to it then save it:
var rootElement = Interfaces.Root;
foreach (var i in intf)
{
var element = new XElement("Interface",
new XElement("name", i),
new XElement("vlan-tagging", XElement.EmptySequence),
new XElement("unit",
new XElement("vlan-id", "10"),
new XElement("family",
new XElement("inet",
new XElement("address",
new XElement("name", "10.10.1.23/24"))))));
rootElement.Add(element);
}
rootElement.Save("Interfaces.xml");

XElement => Add children nodes at run time

So let's assume this is what i want to achieve:
<root>
<name>AAAA</name>
<last>BBBB</last>
<children>
<child>
<name>XXX</name>
<last>TTT</last>
</child>
<child>
<name>OOO</name>
<last>PPP</last>
</child>
</children>
</root>
Not sure if using XElement is the simplest way
but this is what I have so far:
XElement x = new XElement("root",
new XElement("name", "AAA"),
new XElement("last", "BBB"));
Now I have to add the "children" based on some data i have.
There could be 1,2,3,4 ...
so I need to iterate thru my list to get every single child
foreach (Children c in family)
{
x.Add(new XElement("child",
new XElement("name", "XXX"),
new XElement("last", "TTT"));
}
PROBLEM:
Doing this way I will be missing the "CHILDREN Parent node".
If I just add it before the foreach, it will be rendered as a closed node
<children/>
and that's NOT what we want.
QUESTION:
How can I add to the 1st part a parent node and as many as my list has?
Try this:
var x = new XElement("root",
new XElement("name", "AAA"),
new XElement("last", "BBB"),
new XElement("children",
from c in family
select new XElement("child",
new XElement("name", "XXX"),
new XElement("last", "TTT")
)
)
);
XElement root = new XElement("root",
new XElement("name", "AAA"),
new XElement("last", "BBB"));
XElement children = new XElement("children");
foreach (Children c in family)
{
children.Add(new XElement("child",
new XElement("name", c.Name),
new XElement("last", c.Last));
}
root.Add(children);
var children = new XElement("children");
XElement x = new XElement("root",
new XElement("name", "AAA"),
new XElement("last", "BBB"),
children);
foreach (Children c in family)
{
children.Add(new XElement("child",
new XElement("name", "XXX"),
new XElement("last", "TTT"));
}

Categories