How to Get Element Names from XElement Using C#? - c#

I have a Xml and i have to get the element name
<Data>
<Test key="G" modifier="control" />
<Test1 key="E" modifier="control" />
<Test3 />
<Test4 />
</Data>
XDocument xd = XDocument.Load("..\\Cmd.xml");
IEnumerable<XElement> xeCmdData = Cmd.XPathSelectElements(".//Data");
foreach (XElement xeData in xeCmdData)
{
// here i am getting the whole xml how to get Element name ...
// Like <Data>
// <Test key="G" modifier="control" />
// <Test1 key="E" modifier="control" />
// <Test3 />
// <Test4 />
// </Data>
}
How to get Element names ?

XDocument xd = XDocument.Load("..\\Cmd.xml");
IEnumerable<string> names = xd.XPathSelectElements("//Data/*")
.Select(e => e.Name.LocalName);
Or without XPath
IEnumerable<string> names = xd.Descendants("Data")
.Elements()
.Select(e => e.Name.LocalName);
Result:
Test
Test1
Test3
Test4

Related

Get XML attribute Values by its Descendants

I have an XML in this Format and I want to get List of Line ID and its Name
<ArrayOfLines xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<LineStatus ID="0" StatusDetails="">
<BranchDisruptions />
<Line ID="1" Name="Line1" />
<Status ID="GS" CssClass="GoodService" Description="Good Service" IsActive="true">
<StatusType ID="1" Description="Line" />
</Status>
</LineStatus>
<LineStatus ID="1" StatusDetails="">
<BranchDisruptions />
<Line ID="2" Name="Line2" />
<Status ID="GS" CssClass="GoodService" Description="Good Service" IsActive="true">
<StatusType ID="1" Description="Line" />
</Status>
</LineStatus>
</ArrayOfLines>
and This is the code I have written:
String xmlFilePath = #"C:/myXML.xml";
XDocument xmlFile = XDocument.Load(xmlFilePath);
var query = from c in xmlFile.Descendants("LineStatus") select c;
but it is not returning me any results.
Here is my idea but you have to create list "namesList" and "idList" before. Try this:
XDocument xDoc = XDocument.Load("your xml file");
foreach (var elem in xDoc.Document.Descendants("line"))
{
idList.Add(elem.Attribute("ID").Value);
namesList.Add(elem.Attribute("Name").Value);
}
And you have full controll by index of each list to this data. After that you can also create object of these 2 elements
You have an xml namespace, you need to specify it with element names:
XNamespace ns = "http://www.w3.org/2001/XMLSchema-instance";
var query = from c in xmlFile.Descendants(ns + "LineStatus") select c;
Try this...
String xmlFilePath = #"C:/myXML.xml";
XDocument xmlFile = XDocument.Load(xmlFilePath);
var query = (from c in xmlFile.Descendants("Line")
select new {
ID=c.Attribute("ID").Value,
Name=c.Attribute("Name").Value
}).ToList();;

Check whether a particular node exist in xml data

I have an xml data given below. I need to check whether an employee of empName="John" exists in Production department. If exists update the salary otherwise add an employee to the department.
<Company>
<Company Name="ABCDEF" />
<Place="AKR" />
<Production>
<employee empName="John" empId="E11" salary="1000" />
<employee empName="Ivan" empId="E12" salary="3000" />
<employee empName="Paul" empId="E13" salary="1200" />
</Production>
<Marketing>
<employee empName="Keith" empId="EMP11" />
<employee empName="Christina" empId="EMP12" />
</Marketing>
</Company>
I need to check particular node exist in this data using c# linq?
Correct your XML first,
<Company>
<Company Name="ABCDEF" />
<Production>
<employee empName="John" empId="E11" salary="1000" />
<employee empName="Ivan" empId="E12" salary="3000" />
<employee empName="Paul" empId="E13" salary="1200" />
</Production>
<Marketing>
<employee empName="Keith" empId="EMP11" />
<employee empName="Christina" empId="EMP12" />
</Marketing>
</Company>
you can try like this
string filePaths = "XMLFile1.xml";
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(filePaths);
XmlNodeList elements = xmlDoc.GetElementsByTagName("employee");
Boolean found = false;
foreach (XmlElement element in elements)
{
if (element.GetAttribute("empName") == "John")
{
found = true;
break;
}
}
Your XML is invalid; you cannot have a node like <Place="AKR" />
But, after changing it into something valid, you could try using this LINQ statement:
XDocument root = XDocument.Parse(File.ReadAllText("xml.xml"));
IEnumerable<XElement> production = root.Root
.Descendants("Production")
.Where(x => x.Elements("employee")
.Where(e => e.Attribute("empName").Value.Equals("John"))
.Any()
);
if (production.Any())
{
Console.WriteLine("John found...");
}
else
{
Console.WriteLine("No John found");
}
try this:
XmlNode node = xmlDoc.SelectSingleNode(NodeName);

c# sort XElement, with comments

I have an XElement that represents following xml:
<Node>
<Child id="1" /><!-- Comment 1 -->
<Child id="3" /><!-- Comment 3 -->
<Child id="2" /><!-- Comment 2 -->
</Node>
How can I sort the children of Node so that the XElement.ToString() method returns the following?
The comments and text behind the child must be moved along.
<Node>
<Child id="1" /><!-- Comment 1 -->
<Child id="2" /><!-- Comment 2 -->
<Child id="3" /><!-- Comment 3 -->
</Node>
Assuming each element is succeeded by the corresponding comment, try the following:
var xDoc = XDocument.Parse(/* your xml */);
var reordered = xDoc.Root
.Elements("Child")
.Select(el => new {
Element = el,
Comments = el.NodesAfterSelf()
.TakeWhile(n => n.NodeType == XmlNodeType.Comment)
})
.OrderBy(pair => (int)pair.Element.Attribute("id"))
.SelectMany(pair => new [] { pair.Element }.Concat(pair.Comments));
xDoc.Root.ReplaceAll(reordered);
EDIT: edited to allow any (incl. 0) number of comments per element; whitespace was already handled.

How to put a node in a dictionary using LINQ to XML

This is the XML file which I have:
<Root>
<Level1>
<Foo ID="1" Count="20" />
<Foo ID="2" Count="28" />
<Foo ID="3" Count="25" />
</Level1>
</Root>
I only have one Level 1 element in my XML, and inside of it there several Foo nodes.
How can I get that Foo nodes in a dictionary?
I mean Dictionary<int, int>.
var doc = XDocument.Load(fileName);
var dictionary =
doc.Root
.Element("Level1")
.Elements("Foo")
.ToDictionary(
e => (int)e.Attribute("Id"),
e => (int)e.Attribute("Count"));
XElement.Parse("XML here").Descendants("Foo").Select( s => s).ToDictionary( x=> x.Attribute("ID").Value, x=> x.Attribute("Count").Value))

Adding a class instance as value to a dictionary

I've an xml file "Sample.xml"
<RootElement>
<Children>
<Child Name="FirstChild" Start="0" End="2">
<Sibling Name="Test1" />
<Sibling Name="Test2" />
<AdditionalSibling Name="Add_Test_1" />
<AdditionalSibling Name="Add_Test_2" />
<MissingSibling Name="Miss_Test_1" />
<MissingSibling Name="Miss_Test_2" /
</Child>
<Child Name="SecondChild" Start="0" End="2">
<Sibling Name="Test3" />
<Sibling Name="Test4" />
</Child>
<Child Name="ThirdChild" Start="0" End="2">
<Sibling Name="Test5" />
<Sibling Name="Test6" />
</Child>
<Child Name="FourthChild" Start="0" End="2">
<Sibling Name="Test7" />
<Sibling Name="Test8" />
</Child>
<Child Name="FifthChild" Start="0" End="2">
<Sibling Name="Test9" />
<Sibling Name="Test10" />
</Child>
<Child Name="SixthChild" Start="0" End="2">
<Sibling Name="Test11" />
<Sibling Name="Test12" />
</Child>
<MatchedChilds>
<Child Name="FirstChild" />
<Child Name="SecondChild" />
<Child Name="ThirdChild" />
<Child Name="FourthChild" />
<Child Name="FifthChild" />
<Child Name="SixthChild" />
</MatchedChilds>
</Children>
</RootElement>
And a Class "SampleClass"
public class SampleClass
{
string Start;
string End;
List<string> Siblings;
List<string> AdditionalSiblings;
List<string> MissingSiblings;
public SampleClass()
{
Start= "";
End = "";
Siblings = new List<string>();
AdditionalSiblings = new List<string>();
MissingSiblings = new List<string>();
}
public SampleClass( string St, string En,List<string> S, List<string> AS, List<string> MS)
{
Start= St;
End = En;
Siblings = S;
AdditionalSiblings = AS;
MissingSiblings = MS;
}
}
and in another class i've declared a Dictonary Like
Dictionary<string, SampleClass> m_dictSample = new Dictionary<string, SampleClass>();
i need to fill this dictonary with the contents of the file ..
I'm using Xml Linq for this..
XDocument l_XDOC = XDocument.Load(Application.StartupPath + "\\Sample.xml");
m_dictSample = (from element in l_XDOC.Descendants("Child")
group element by element.Attribute("Name").Value into KeyGroup
select KeyGroup )
.ToDictionary(grp => grp.Key,
grp => new
SampleClass(grp.Attributes("Start").ToList()[0].Value.ToString(),
grp.Attributes("End").ToList()[0].Value.ToString(),
grp.Descendants("Sibling").Attributes("Name").Select(l_Temp => l_Temp.Value).ToList(),
grp.Descendants("AdditionalSibling").Attributes("Name").Select(l_Temp => l_Temp.Value).ToList(),
grp.Descendants("MissingSibling").Attributes("Name").Select(l_Temp => l_Temp.Value).ToList()));
This query is working properly for the above described file.
But if the file have more than one Element with same name, or an element with no "start" and "end" attribute make an exception while
executing the query.
I've problem with the following lines
grp.Attributes("Start").ToList()[0].Value.ToString(),
grp.Attributes("End").ToList()[0].Value.ToString()
please give me a better way to do this
And i need to fill a listView with the contents of the Dictonary like
S.no Child Siblings Additional Siblings Missing Siblings
1 FirstChild Test1,Test2 Add_Test_1,Add_Test_2 Miss_Test_1,Miss_Test_2
2 SecondChild Test3,Test4
3 ThirdChild Test5,Test6
now i'm using for loop for this
please give me a better way to do this..
You can't use a Dictionary you have to use a Lookup collection
Dictionaries require that each key has a 1-1 mapping to a unique value.
What you're looking for is a Lookup collection.
See this for more info.
Given the way that you have written your query I don't see why you'd be getting an exception if you had two Child elements with the same name. If anything their data would just get combined into a single key instance in your dictionary. To fix the exception you receive when a Start attribute doesn't exist just do a conditional operator test ? : to see if results were returned from your attribute query. That said the below code should work for you with the disclaimer that just because this works doesn't mean it's best practice. In many ways I am a LINQ neophyte myself.
Dictionary<string, SampleClass> dict =
(from element in xDoc.Descendants("Child")
group element by element.Attribute("Name").Value
into kGrp
select kGrp)
.ToDictionary(grp => grp.Key,
grp => new SampleClass
{
Start = grp.Attributes("Start").Count() > 0
? grp.Attributes("Start")
.ToList()[0].Value.ToString()
: String.Empty
,End = grp.Attributes("End").Count() > 0
? grp.Attributes("End")
.ToList()[0].Value.ToString()
: String.Empty
,Siblings =
grp.Descendants("Sibling")
.Attributes("Name")
.Select(l_Temp => l_Temp.Value).ToList()
,AdditionalSiblings =
grp.Descendants("AdditionalSibling")
.Attributes("Name")
.Select(l_Temp => l_Temp.Value).ToList()
,MissingSiblings =
grp.Descendants("MissingSibling")
.Attributes("Name")
.Select(l_Temp => l_Temp.Value).ToList()
});

Categories

Resources