Child Nodes in XML File - c#

I am trying to get the child nodes in my xml file and print it out..however i cannot. It is just printing one element instead of all. please help.
XDocument doc = XDocument.Load(GlobalClass.GlobalUrl);
XElement xelement = XElement.Load(GlobalClass.GlobalUrl);
var query = from nm in xelement.Elements("EmployeeFinance")
where (int)nm.Element("EmpPersonal_Id") == empID
select new AllowancePaid
{
Income_ID = (decimal)nm.Element("Allowance-Grade")
.Element("Amount")
};
var x = query.ToList();
foreach (var ele in x) {
Debug.WriteLine(ele.Income_ID);
}
My XML File
<EmployeeFinance>
<EmployeeEmploy_Id>4891</EmployeeEmploy_Id>
<EmpPersonal_Id>28407</EmpPersonal_Id>
<Employee_Number>11715</Employee_Number>
<Allowance-Grade>
<Amount BenListID="32">6000.00</Amount>
<Amount BenListID="59">100000.00</Amount>
</Allowance-Grade>
</EmployeeFinance>
Adding the elements
var result = from element in doc.Descendants("EmployeeFinance")
where int.Parse(element.Element("EmpPersonal_Id").Value) == tt.Employee_Personal_InfoEmp_id
select element;
foreach (var ele in result)
{
ele.Element("Allowance-Grade")
.Add(new XElement("Amount", new XAttribute("BenListID", tt.ID), tt.Amount));
doc.Save(GlobalClass.GlobalUrl);
}

problem is you selecting one amount node .Element("Amount") but there are many nodes. Change it to .Elements("Amount") and need to change few places. I haven't tested but logic should something like below will work
`
var query = from nm in xelement.Elements("EmployeeFinance")
where (int)nm.Element("EmpPersonal_Id") == empID
select new AllowancePaid
{
AllowanceList = nm.Element("Allowance-Grade").Elements("Amount").Select( a=>(decimal)a.Value).ToList()
};
foreach (var ele in query) {
foreach (var a in ele.AllowanceList) {
Debug.WriteLine(a);
}
}

XDocument xelement = XDocument.Parse(xml);
var query = from nm in xelement.Elements("EmployeeFinance")
where (int)nm.Element("EmpPersonal_Id") == 28407
select new
{
Amounts = nm.Element("Allowance-Grade")
.Elements("Amount")
.Select(
row =>
new {
id = row.Value
}
).ToList()
};
var x = query.ToList();
foreach (var ele in x)
{
foreach(var a in ele.Amounts)
Console.WriteLine(a);
}

Related

Get Connected Elements in Autodesk Inventor via API

We have Autodesk Inventor and created a C# Addon.
In this we loop through all Objects like this:
foreach (CurrencyAPIv2.IAssetInstance s in objects)
{
var c = s.NativeObject as ComponentOccurrence;
}
How can we get the connected Object of an Object (the one which is snapped to it). And also the Info to which connector it is connected (snapped)
Michael Navara:
Can you be more specific? CurrencyAPIv2.IAssetInstance is not a member of Inventor API
using CurrencyAPIv2 = Autodesk.Factory.PublicAPI.Currency.v2;
We solved it with the XML-files which can also be watched in AttributeHelper:
void LoadConnectors(Document document, List<ConnectionElement> connections, List<ConnectedComponent> components)
{
var am = document.AttributeManager;
var d = new Dictionary<string, string>();
var entities = am.FindObjects("*", "*");
foreach (var e in entities)
{
try
{
dynamic o = e;
foreach (AttributeSet attrS in o.AttributeSets)
{
foreach (Inventor.Attribute a in attrS)
{
d.Add(o.Name, a.Value as string);
}
}
}
catch(Exception)
{ }
}
foreach (var element in d)
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(element.Value);
var connectionNodes = xmlDoc.SelectNodes("//ObjectData[#Type='42']");
var componentNodes = xmlDoc.SelectNodes("//ObjectData[#Type='38']");
// Verbindungen
if (connectionNodes.Count > 0)
{
var link1Node = xmlDoc.SelectSingleNode("//ObjectData/Link1") as XmlElement;
var link2Node = xmlDoc.SelectSingleNode("//ObjectData/Link2") as XmlElement;
var connection = new ConnectionElement();
connection.Name = element.Key;
connection.Link1 = link1Node.GetAttribute("VAL");
connection.Link2 = link2Node.GetAttribute("VAL");
connections.Add(connection);
}
// Komponenten
else if (componentNodes.Count > 0)
{
var componentConnectorNodes = xmlDoc.SelectNodes("//ObjectData/Connector");
var componentConnectors = new List<ComponentConnector>();
foreach (XmlNode cc in componentConnectorNodes)
{
var idNode = cc.SelectSingleNode("Id") as XmlElement;
var displayNameNode = cc.SelectSingleNode("DisplayName") as XmlElement;
var connector = new ComponentConnector();
connector.DisplayName = displayNameNode.GetAttribute("VAL");
connector.Id = idNode.GetAttribute("VAL");
componentConnectors.Add(connector);
}
if (components.FirstOrDefault(x => x.Name == element.Key) != null)
{
components.FirstOrDefault(x => x.Name == element.Key).Connectors.AddRange(componentConnectors);
}
else
{
var component = new ConnectedComponent();
component.Name = element.Key;
component.Connectors = new List<ComponentConnector>();
component.Connectors.AddRange(componentConnectors);
components.Add(component);
}
}
}
}

Reading XML Data and Storing in DataTable

I have an log file like this..
This is the segment 1
============================
<MAINELEMENT><ELEMENT1>10-10-2013 10:10:22.444</ELEMENT1><ELEMENT2>1111</ELEMENT2>
<ELEMENT3>Message 1</ELEMENT3></MAINELEMENT>
<MAINELEMENT><ELEMENT1>10-10-2013 10:10:22.555</ELEMENT1><ELEMENT2>1111</ELEMENT2>
<ELEMENT3>Message 2</ELEMENT3></MAINELEMENT>
This is the segment 2
============================
<MAINELEMENT><ELEMENT1>10-11-2012 10:10:22.444</ELEMENT1><ELEMENT2>2222</ELEMENT2>
<ELEMENT3>Message 1</ELEMENT3></MAINELEMENT>
<MAINELEMENT><ELEMENT1>10-11-2012 10:10:22.555</ELEMENT1><ELEMENT2>2222</ELEMENT2>
<ELEMENT3>Message 2</ELEMENT3></MAINELEMENT>
How can I read this into DataTable excluding the data This is the segment 1 and This is the segment 2 and ====== lines completely.
I would like to have the Datatable as with Columns as "ELEMENT1", "ELEMENT2", "ELEMENT3" and fill the details with the content between those tags in the order of print of line.
It should not change the sequence of the order of records in the table while inserting.
HtmlAgilityPack seems to be a good tool for what you need:
using HtmlAgilityPack;
class Program
{
static void Main(string[] args)
{
var doc = new HtmlDocument();
doc.Load("log.txt");
var dt = new DataTable();
bool hasColumns = false;
foreach (HtmlNode row in doc
.DocumentNode
.SelectNodes("//mainelement"))
{
if (!hasColumns)
{
hasColumns = true;
foreach (var column in row.ChildNodes
.Where(node => node.GetType() == typeof(HtmlNode)))
{
dt.Columns.Add(column.Name);
}
}
dt.Rows.Add(row.ChildNodes
.Where(node => node.GetType() == typeof(HtmlNode))
.Select(node => node.InnerText).ToArray());
}
}
}
could do this, where stringData is the data from the file you have
var array = stringData.Split(new[] { "============================" }, StringSplitOptions.RemoveEmptyEntries);
var document = new XDocument(new XElement("Root"));
foreach (var item in array)
{
if(!item.Contains("<"))
continue;
var subDocument = XDocument.Parse("<Root>" + item.Substring(0, item.LastIndexOf('>') + 1) + "</Root>");
foreach (var element in subDocument.Root.Descendants("MAINELEMENT"))
{
document.Root.Add(element);
}
}
var table = new DataTable();
table.Columns.Add("ELEMENT1");
table.Columns.Add("ELEMENT2");
table.Columns.Add("ELEMENT3");
var rows =
document.Descendants("MAINELEMENT").Select(el =>
{
var row = table.NewRow();
row["ELEMENT1"] = el.Element("ELEMENT1").Value;
row["ELEMENT2"] = el.Element("ELEMENT2").Value;
row["ELEMENT3"] = el.Element("ELEMENT3").Value;
return row;
});
foreach (var row in rows)
{
table.Rows.Add(row);
}
foreach (DataRow dataRow in table.Rows)
{
Console.WriteLine("{0},{1},{2}", dataRow["ELEMENT1"], dataRow["ELEMENT2"], dataRow["ELEMENT3"]);
}
I'm not so sure where you problem is.
You can use XElement for reading the xml and manually creating DataTable.
For Reading the XML See Xml Parsing using XElement
Then you can create dynamically the datatable.
Heres an example of creating a datatable in code
https://sites.google.com/site/bhargavaclub/datatablec
But why do you want to use a DataTable ? There are a lot of downsides...

LINQ XML- Read XML data

I am having trouble with LINQ query for XML and can't solve
I am trying to extract the element values
Here is the XML
<response>
<make>DODGE</make>
<make>CHRYSLER</make>
<make>JEEP</make>
<make>RAM</make>
.......etc
</response>
Here is the code I have so far...
XElement parsedXml3 = XElement.Parse(xml3);
var query2 = from m in parsedXml3.Descendants("response")
select m.Elements("make").Select(e => e.Value);
List<string> ls = new List<string>();
foreach (var o in query2)
{
ls = o.ToList();
}
ls.Sort();
Thanks for your help - extended explanations would be great
Try This.
XElement parsedXml3 = XElement.Parse(xml3); //parse your xml string
There is no need to use parsedXml3.Descendants("response") because response is root node here
var makes= parsedXml3.Elements("make") //Get All make Elements
.Select(x=>x.Value).ToList(); //Select Value from make Element
//and Store in List<string>
makes.Sort();
foreach (var make in makes)
{
Console.WriteLine(make);
}
or you can modify your code to
XElement parsedXml3 = XElement.Parse(xml3);
var ls= (from m in parsedXml3.Descendants("make")
select m.Value).ToList();
//List<string> ls = new List<string>();
//foreach (var o in query2)
//{
// ls.Add(o);
//}
ls.Sort();

C# Groupby Linq and foreach

I need a more efficient way of producing multiple files from my data group.
Im using a List<MyObject> type and my object has some public properties in which I need to group the data by.
I have heard of Linq and it sounds like something I could use. However Im not sure how to go about it.
I need to produce a text file for each STATE, so grouping all the MyObjects (people) by state, then running a foreach look on them to build the TEXT file.
void Main()
{
List<MyObject> lst = new List<MyObject>();
lst.Add(new MyObject{ name = "bill", state = "nsw", url = "microsoft.com"});
lst.Add(new MyObject{ name = "ted", state = "vic", url = "apple.com"});
lst.Add(new MyObject{ name = "jesse", state = "nsw", url = "google.com"});
lst.Add(new MyObject{ name = "james", state = "qld", url = "toshiba.com"});
string builder = "";
foreach (MyObject item in myObjects) {
builder += item.name + "\r\n";
builder += item.url + "\r\n" + "\r\n\r\n";
}
and out to the `StreamWriter` will be the filenames by state.
In total for the above data I need 3 files;
-nsw.txt
-vic.txt
-qld.txt
Something like this, perhaps?
var groups = lst.GroupBy(x => x.state);
foreach (var group in groups)
{
using (var f = new StreamWriter(group.Key + ".txt"))
{
foreach (var item in group)
{
f.WriteLine(item.name);
f.WriteLine(item.url);
}
}
}
You def. could use LINQ here.
lst.GroupBy(r=> r.state).ToList().ForEach(r=> {
//state= r.Key
//
foreach (var v in r)
{
}
});
The thing about linq. If you want to know how to do something in it. Think "how would I do this in SQL". The keywords are for the most part the same.
You can actually produce entire content with LINQ:
var entryFormat = "{1}{0}{2}{0}{0}{0}";
var groupsToPrint = lst
.GroupBy(p => p.state)
.Select(g => new
{
State = g.Key,
// produce file content on-the-fly from group entries
Content = string.Join("", g.Select(v => string.Format(entryFormat,
Environment.NewLine, v.name, v.url)))
});
var fileNameFormat = "{0}.txt";
foreach (var entry in groupsToPrint)
{
var fileName = string.Format(fileNameFormat, entry.State);
File.WriteAllText(fileName, entry.Content);
}
Something like...
string builderNsw = "";
foreach (MyObject item in lst.Where(o=>o.state == 'nsw')) {
builderNsw += item.name + "\r\n";
builderNsw += item.url + "\r\n" + "\r\n\r\n";
}
...but there are probably many ways to achieve this.
Same as Above - Iterating through groups by group, can get group name also
int itemCounter = 1;
IEnumerable<DataRow> sequence = Datatables.AsEnumerable();
var GroupedData = from d in sequence group d by d["panelName"]; // GroupedData is now of type IEnumerable<IGrouping<int, Document>>
foreach (var GroupList in GroupedData) // GroupList = "document group", of type IGrouping<int, Document>
{
bool chk = false;
foreach (var Item in GroupList)
{
if (chk == false) // means when header is not inserted
{
var groupName = "Panel Name : " + Item["panelName"].ToString();
chk = true;
}
var count = itemCounter.ToString();
var itemRef = Item["reference"].ToString();
itemCounter++;
}
}

Add items if equal to (XML feed reading)

i am reading an XML feed and adding results like this:
XElement _xml;
try
{
if (!e.Cancelled)
{
_xml = XElement.Parse(e.Result);
Results.Items.Clear();
foreach (XElement value in _xml.Elements("runner").Elements("rr_event"))
{
FeedItem _item = new FeedItem();
_item.Title = value.Element("title").Value;
_item.Description = Regex.Replace(value.Element("description").Value,
#"<(.|\n)*?>", String.Empty);
_item.Sector = value.Element("sector").Value;
Results.Items.Add(_item);
}
}
}
My aim is to only add to Results if the XML tag "Sector" text equals to "A"
Many thanks. Dan
Totally agree with vortex, just add if("A".equals(_item.Sector)).
XElement _xml;
try
{
if (!e.Cancelled)
{
_xml = XElement.Parse(e.Result);
Results.Items.Clear();
foreach (XElement value in _xml.Elements("runner").Elements("rr_event"))
{
FeedItem _item = new FeedItem();
_item.Title = value.Element("title").Value;
_item.Description = Regex.Replace(value.Element("description").Value,
#"<(.|\n)*?>", String.Empty);
_item.Sector = value.Element("sector").Value;
if("A".equals(_item.Sector)) Results.Items.Add(_item);
}
}
}
This should do it.

Categories