How to read specific fields from XML and load into Oracle db - c#

my XML :
- <resources start="0" count="188">-
- <resource classname="Quote">
<field name="name">USD/GEL</field>
<field name="price">2.418900</field>
<field name="symbol">GEL=X</field>
<field name="ts">1488758461</field>
<field name="type">currency</field>
<field name="utctime">2017-03-06T00:01:01+0000</field>
<field name="volume">0</field>
</resource>-
</resources>
C# Code:
var xmlNodes = xElement.Descendants("resource")
.Select(e => new
{
ConvertFrom = e.Attribute("symbol").Value,
ConvRate = e.Attribute("price").Value,
ConvDate = e.Attribute("utctime").Value
});
I tried the above code to fetch and load into oracle but i got a below error.
System.Linq.Enumerable+WhereSelectEnumerableIterator2[System.Xml.Linq.XElement,<>f__AnonymousType03[System.String,System.String,System.String]]
Please help me to resolve this issue.

I think you have misunderstood Attribute method, the name of the attribute is name, symbol is the value, so your query could be this way:
var xmlNodes = xElement.Descendants("resource")
.Select(e => new
{
ConvertFrom = (string)e.Elements().FistOrDefault(r=>r.Attribute("name").Value=="symbol"),
ConvRate = (string)e.Elements().FistOrDefault(r=>r.Attribute("name").Value=="price"),
ConvDate = (DateTime)e.Elements().FistOrDefault(r=>r.Attribute("name").Value=="utctime"),
});

Related

Get value from XML code where attribute has particular value [using XElement]

I am attempting to retrieve values from certain nodes in an XML response by using XElement where the attribute value is "id=x".
This is what the XML response looks like.
<customfields>
<group id="6" title="Help Desk Ticket Categories" displayorder="1">
<field id="73" title="Second level classification" type="6" name="zscyz3a30h1q"><![CDATA[-- unassigned --]]></field>
</group>
<group id="9" title="For CS" displayorder="4">
<field id="82" title="CS Root Cause Classification " type="6" name="pye19ntzyp8v"><![CDATA[--Unassigned--]]></field>
<field id="84" title="Staff Responsible" type="6" name="7gy8bfu8tidv"><![CDATA[-- unassigned --]]></field>
<field id="93" title="Customer Package" type="6" name="fxk9rqtlw0fa"><![CDATA[--Unassigned--]]></field>
</group>
<group id="2" title="Client Info" displayorder="3">
<field id="5" title="Customer Name" type="1" name="77004d0323"><![CDATA[BigG]]></field>
<field id="17" title="Account Number" type="1" name="d1abccc1a0" /><![CDATA[123]]></field>
<field id="16" title="Contact Name" type="1" name="93d2b9adf1" /><![CDATA[george]]></field>
<field id="13" title="Phone No." type="1" name="0aa31be4b8" /><![CDATA[456]]></field>
</group>
</customfields>
This is the code I'm using now (which works), but I'd rather retrieve values for field with "id"="5" rather than have the value retrieved through a descendant index.
XElement root = XElement.Parse(GetTicketCustomFields(ticketID));
kCustomer = (string)(from el in root.Descendants("field") select el).ElementAt(4);
kAccountNumber = (string)(from el in root.Descendants("field") select el).ElementAt(5);
kName = (string)(from el in root.Descendants("field") select el).ElementAt(6);
kPhone = (string)(from el in root.Descendants("field") select el).ElementAt(7);
Thanks for
I would use XPath
var root = XDocument.Parse(xmlstring);
var accountNumber = root.XPathSelectElement("//field[#id='17']").Value;
or
var accountNumber = root.XPathSelectElement("//field[#title='Account Number']").Value;
Using Linq2Xml is also possible
var accountNumber = root.Descendants("field")
.FirstOrDefault(F => F.Attribute("id").Value == "17")
.Value;
Use XPath as #L.B. suggests.
If you're using Visual Studio there's a plugin written by yours truly which can help you find the XPath of a given element or attribute, to get you on your way: XPath Information

XDocument does not return the expected node

I try to work with the XDocument in C# but have some problems to receive the desired elements. Here is my sample xml
<?xml version="1.0" encoding="UTF-8"?>
<xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve">
<f href="#{pdffile}"/>
<ids modified="BF43C70442ECB74FA49833BBA44D4679" original="B4870CC046121A41B7D8F0838C87256D"/>
<fields>
<field name="FormInstanceID"><value>#{instanceid}</value></field>
<field name="meta_7"><value>#{meta_7}</value></field>
<field name="meta_6"><value>#{meta_6}</value></field>
<field name="meta_8"><value>#{meta_8}</value></field>
<field name="meta_3"><value>#{meta_3}</value></field>
<field name="meta_2"><value>#{meta_2}</value></field>
<field name="meta_5"><value>#{meta_5}</value></field>
<field name="meta_4"><value>#{meta_4}</value></field>
<field name="meta_1"><value>#{meta_1}</value></field>
<field name="tag_5"><value>#{tag_5}</value></field>
<field name="tag_1"><value>#{tag_1}</value></field>
<field name="tag_2"><value>#{tag_2}</value></field>
<field name="tag_3"><value>#{tag_3}</value></field>
<field name="TAGS"><value>#{TAGS}</value></field>
<field name="tag_4"><value>#{tag_4}</value></field>
<field name="qr"><value>#{qr}</value></field>
<field name="metadata"><value>#{metadata}</value></field>
<field name="pdx.dynform.email"><value>#{pdx.dynform.email}</value></field>
</fields>
</xfdf>
Assuming the given XML I want to extract with XDocument the field values. Currently I do no receive any entry by using this approach
XDocument xfdfData = XDocument.Load(xfdf);
var result = xfdfData.Descendants("fields");
The file is sucessfully loaded in the xfdfData object but the Descendants("fields") does find any nodes.
You don't have a fields element which isn't in a namespace, which is what you're asking for. Due to this in the root element:
xmlns="http://ns.adobe.com/xfdf/"
... the default namespace URI for the descendant nodes is http://ns.adobe.com/xfdf/. So you want:
XNamespace ns = "http://ns.adobe.com/xfdf/";
XDocument doc= XDocument.Load(xfdf);
var result = doc.Descendants(ns + "fields");
Or to find the field elements themselves:
XNamespace ns = "http://ns.adobe.com/xfdf/";
XDocument doc= XDocument.Load(xfdf);
var fields = doc.Descendants(ns + "field");

Parsing XML using LINQ in c#

In this xml file (http://www.studiovincent.net/list.xml):
<list version="1.0">
<meta>
<type>resource-list</type>
</meta>
<resources start="0" count="4">
<resource classname="Quote">
<field name="name">Vincent</field>
<field name="username">Hill</field>
<field name="age">31</field>
<field name="hair">black</field>
</resource>
<resource classname="Quote">
<field name="name">John</field>
<field name="username">Tedelon</field>
<field name="age">27</field>
<field name="hair">brown</field>
</resource>
<resource classname="Quote">
<field name="name">Michael</field>
<field name="username">Lopez</field>
<field name="age">20</field>
<field name="hair">red</field>
</resource>
<resource classname="Quote">
<field name="name">Frank</field>
<field name="username">Lopez</field>
<field name="age">25</field>
<field name="hair">black</field>
</resource>
</resources>
</list>
using this code:
using System.Xml;
using.System.Xml.Linq;
XmlReader reader = XmlReader.Create("http://www.studiovincent.net/list.xml");
XElement el = XElement.Load(reader);
reader.Close();
var items = el.Elements("resources").Elements("resource").Descendants().DescendantNodes();
var items = from item in el.Elements("resources").Elements("resource").Descendants()
where item.Attribute("name").Value == "name" select item.FirstNode;
foreach (XNode node in items)
{
Console.WriteLine(node.ToString());
}
I have this OUTPUT:
Vincent
John
Michael
Frank
Code working very good, but I need get value 31 which corresponds field name="age" where field name="name" is Vincent. How Can I get this result?
I recommend you do as you would when reading XML naturally.
In your code, try to find all the fields with the name attribute set to "name".
This process cannot be used to associate a name with an age. It is more natural to read the XML and check all resource elements. Then add to this element some information described in the field elements.
// Using LINQ to SQL
XDocument document = XDocument.Load("http://www.studiovincent.net/list.xml"); // Loads the XML document.
XElement resourcesElement = document.Root.Element("resources"); // Gets the "resources" element that is in the root "list" of the document.
XElement resourceElementVincent = (from resourceElement in resourcesElement.Elements("resource")// Gets all the "resource" elements in the "resources" element
let fieldNameElement = resourceElement.Elements("field").Single(fieldElement => fieldElement.Attribute("name").Value == "name") // Gets the field that contains the name (there one and only one "name" field in the "resource" element -> use of Single())
where fieldNameElement.Value == "Vincent" // To get only resources called "Vincent"
select resourceElement).Single(); // We suppose there is one and only 1 resource called "Vincent" -> Use of Single()
XElement fieldAgeElement = resourceElementVincent.Elements("field").Single(fieldElement => fieldElement.Attribute("name").Value == "age"); // Gets the corresponding "age" field
int age = int.Parse(fieldAgeElement.Value, CultureInfo.InvariantCulture); // Gets the age by Parse it as an integer
Console.WriteLine(age);
Does it do what you want?
Consider this below XML is there as one of the SQL table's column.
<Root>
<Name>Dinesh</Name>
<Id>2</Id>
</Root>
The objective of the query is to fetch the Name from the XML. In this example we will fetch the 'Dinesh' as the value.
var Query = (from t in dbContext.Employee.AsEnumerable()
where t.active == true
select new Employee
{
Id = t.AtpEventId,
Name = XDocument.Parse(t.Content).Descendants("Root").Descendants("Name").ToList().
Select(node => node.Value.ToString()).FirstOrDefault()
});
Note the following:
t.active == true is just an example to make some condition if needed.
Please note, in the above LINQ query, always use the AsEnumerable, as I did in the first line.
Descendants("Root").Descendants("Name") - here "Root" should be the element matching with the XML, and under Root we have Name element.

Select XML node value by attribute value with multiple levels

I'm looking to get to value further in the XML code than I've seen examples for and with more attributes to consider.
The XML code is:
<?xml version="1.0"?>
<mysqldump xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<database name="Members">
<table_structure name="Logins">
<field Field="ID" Type="int(100)" Null="NO" Key="PRI" Extra="auto_increment" Comment="" />
<field Field="Username" Type="text" Null="YES" Key="" Extra="" Comment="" />
<field Field="Password" Type="text" Null="YES" Key="" Extra="" Comment="" />
<key Table="Logins" Non_unique="0" Key_name="PRIMARY" Seq_in_index="1" Column_name="ID" Collation="A" Cardinality="1" Null="" Index_type="BTREE" Comment="" />
<options Name="Logins" Engine="MyISAM" Version="10" Row_format="Dynamic" Rows="1" Avg_row_length="20" Data_length="40" Max_data_length="281474976710655" Index_length="2048" Data_free="20" Auto_increment="3" Create_time="2011-10-14 19:30:57" Update_time="2011-10-14 19:32:21" Collation="latin1_swedish_ci" Create_options="" Comment="" />
</table_structure>
<table_data name="Logins">
<row>
<field name="ID">1</field>
<field name="Username">MyName</field>
<field name="Password">MyPassowrd</field>
</row>
<row>
<field name="ID">2</field>
<field name="Username">MyName2</field>
<field name="Password">MyPassowrd2</field>
</row>
</table_data>
</database>
</mysqldump>
I'm trying to get to 1, MyName and Password to then enter them into an SQL database.
The issue I'm having is getting through the multiple levels:
<database name="Members">
<table_data name="Logins">
<row>
<field name="ID">
With all the examples I'm finding only ones showing 1 or 2 levels.
This seems to work,
XElement xe = XElement.Load("C:\\PATH.xml");
int count = xe.Descendants("row").Count();
var items = xe.Descendants("field").Where(n => (string)n.Attribute("name") == "ID").ToList();
var items2 = xe.Descendants("field").Where(n => (string)n.Attribute("name") == "Username").ToList();
var items3 = xe.Descendants("field").Where(n => (string)n.Attribute("name") == "Password").ToList();
for (int i = 0; i < count; i++)
{
string res = items[i].Value.ToString();
string res2 = items2[i].Value.ToString();
string res3 = items3[i].Value.ToString();
}
I've got an ID, but I now need all its other elements in its row.
That is,
if (id = 2)
{
string name = username.value;
string password = password.value;
}
where name will result in myName2 and password will be MyPassword2.
I don't want to put usernames and passwords in a list.
Any advice again?
Try with LINQ to XML.
Here you have a tutorial.

XML String into a DataGridView

I am currently working with a webservice to pull a report about users in a remote support system.
After pulling my report and receiving the result, I am given the following string back by the method:
<report>
<header>
<field id="0">Source</field>
<field id="1">Session ID</field>
<field id="2">Date</field>
<field id="3">Name</field>
<field id="24">Technician Name</field>
<field id="25">Technician ID</field>
</header>
<data>
<row>
<field id="0">Email</field>
<field id="1">55037806</field>
<field id="2">4/13/2010 2:28:06 AM</field>
<field id="3">Bill Gates</field>
<field id="24">John</field>
<field id="25">1821852</field>
</row>
<row>
<field id="0">Telephone</field>
<field id="1">55034548</field>
<field id="2">4/13/2010 12:59:44 AM</field>
<field id="3">Steve Jobs</field>
<field id="24">John</field>
<field id="25">1821852</field>
</row>
</data>
</report>
After receiving this string, I need to take it and display the actual data in a datagridview. I've tried putting it into an XMLDocument then reading that, but it seems to keep failing. Just interested in another set of eyes :) Application is written in C# in VS2010.
You could use Linq to XML to build a DataTable with the column names from the XML file, then set that table as the DataSource of the DataGridView :
string xml = theWebService.TheMethod();
XDocument doc = XDocument.Parse(xml);
var queryHeaders =
from field in doc.Root.Element("header").Elements("field")
select new
{
Id = field.Attribute("id").Value,
Name = field.Value
};
var headers = queryHeaders.ToDictionary(f => f.Id, f => f.Name);
DataTable table = new DataTable();
foreach (var kvp in headers)
{
table.Columns.Add(kvp.Value);
}
Func<XElement, DataRow> rowGenerator =
element =>
{
var row = table.NewRow();
foreach (var field in element.Elements("field"))
{
string fieldId = field.Attribute("id").Value;
string columnName = headers[fieldId];
string value = field.Value;
row[columnName] = value;
}
return row;
};
var rows =
from rowElement in doc.Root.Element("data").Elements("row")
select rowGenerator(rowElement);
foreach (var row in rows)
{
table.Rows.Add(row);
}
dataGridView.AutoGenerateColumns = true;
dataGridView.DataSource = table;
Note that the code above only works if all fields have distinct names. If that's not the case, you might want to use the field ID as the DataColumn name, and change the headers of the DGV with the actual field names

Categories