I have a XML column in a table contains a collection of data. Every record may hold a different collection type like sometimes customers data and sometimes invoices data etc.
How can I read that cell & convert it to a table in order to bind it to a data grid, so the collection some times looks like that
<ArrayOfReceiptTransfer_Receipt xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ReceiptTransfer_Receipt>
<ReceiptTransfer_Receipt_ID>77491</ReceiptTransfer_Receipt_ID>
<ReceiptTransferID>17839</ReceiptTransferID>
<ReceiptID>74080</ReceiptID>
<Amount>500.00</Amount>
</ReceiptTransfer_Receipt>
</ArrayOfReceiptTransfer_Receipt>
And sometimes looks like
<ArrayOfInvoiceBudgetItem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<InvoiceBudgetItem>
<InvoiceID>21978</InvoiceID>
<BudgetItemID>1473</BudgetItemID>
<Amount>12</Amount>
</InvoiceBudgetItem>
<InvoiceBudgetItem>
<InvoiceID>21978</InvoiceID>
<BudgetItemID>1475</BudgetItemID>
<Amount>11</Amount>
</InvoiceBudgetItem>
</ArrayOfInvoiceBudgetItem>
You already have one root tag so this will also work
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
string input =
"<ArrayOfReceiptTransfer_Receipt xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">" +
"<ReceiptTransfer_Receipt>" +
"<ReceiptTransfer_Receipt_ID>77491</ReceiptTransfer_Receipt_ID>" +
"<ReceiptTransferID>17839</ReceiptTransferID>" +
"<ReceiptID>74080</ReceiptID>" +
"<Amount>500.00</Amount>" +
"</ReceiptTransfer_Receipt>" +
"</ArrayOfReceiptTransfer_Receipt>";
string xml = string.Format("<?xml version=\"1.0\" encoding=\"utf-8\"?>{0}", input);
StringReader reader = new StringReader(xml);
DataSet ds = new DataSet();
ds.ReadXml(reader);
dataGridView1.DataSource = ds.Tables[0];
}
}
}
Try this
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
string input =
"<ArrayOfReceiptTransfer_Receipt xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">" +
"<ReceiptTransfer_Receipt>" +
"<ReceiptTransfer_Receipt_ID>77491</ReceiptTransfer_Receipt_ID>" +
"<ReceiptTransferID>17839</ReceiptTransferID>" +
"<ReceiptID>74080</ReceiptID>" +
"<Amount>500.00</Amount>" +
"</ReceiptTransfer_Receipt>" +
"</ArrayOfReceiptTransfer_Receipt>";
string xml = string.Format("<?xml version=\"1.0\" encoding=\"utf-8\"?><root>{0}</root>", input);
StringReader reader = new StringReader(xml);
DataSet ds = new DataSet();
ds.ReadXml(reader);
dataGridView1.DataSource = ds.Tables[1];
}
}
}
Related
I have the following xml
<lists>
<list Group="3">More_lists_go_here</list>
</lists>
What I want is both the list element value which is More_lists_go_here and the Group attribute value which is 3.
What I have tried so far is
XmlDocument doc = new XmlDocument();
doc.LoadXml("<list Group=\"3\">More_lists_go_here</list>");
XmlElement root = doc.DocumentElement;
string value = root.Descendants("lists").Elements("list").Select(x => (string)x.Attribute("Group")).ToList();
what that gets me is
value = 3
what I want is both 3 and More_lists_go_here for string value
Use xml linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication40
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
string input = "<lists><list Group=\"3\">More_lists_go_here</list></lists>";
XDocument doc = XDocument.Parse(input);
var results = doc.Descendants("list").Select(x => new { group = (string)x.Attribute("Group"), value = (string)x }).ToList();
}
}
}
Is that possible to loop element with the same orientation of fields.
<?xml version="1.0" encoding="utf-8"?>
<xml>
<document>
<sls>
<ppsitecode>0062</ppsitecode>
<ppsitedesc><![CDATA[AAAAAAA]]></ppsitedesc>
<ppqty>1.00</ppqty>
<ppunit>C24</ppunit>
<ppsitecode>0269</ppsitecode>
<ppsitedesc><![CDATA[BBBBBBB]]></ppsitedesc>
<ppqty>1.00</ppqty>
<ppunit>C24</ppunit>
<ppsitecode>2546</ppsitecode>
<ppsitedesc><![CDATA[CCCCCCC]]></ppsitedesc>
<ppqty>1.00</ppqty>
<ppunit>C24</ppunit>
</sls>
</document>
</xml>
Using the xml file above. Please refer to the desire output below:
ppsitecode ppsitedesc ppqty ppunit
0062 AAAAAAA 1.00 C24
0269 BBBBBBB 1.00 C24
2546 CCCCCCC 1.00 C24
Use xml linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Data;
namespace ConsoleApplication83
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
XElement sls = doc.Descendants("sls").FirstOrDefault();
DataTable dt = new DataTable();
string[] columns = sls.Elements().Select(x => x.Name.LocalName).Distinct().ToArray();
foreach (string column in columns)
{
dt.Columns.Add(column, typeof(string));
}
DataRow newRow = null;
foreach (XElement element in sls.Elements())
{
string columnName = element.Name.LocalName;
if (columnName == "ppsitecode") newRow = dt.Rows.Add();
newRow[columnName] = (string)element;
}
}
}
}
I want to grab UPC value from the following XML example node, but the current doc.SelectNodes fails to grab that value. I am using XmlDocument to process my XML. Can you fix my code to grab UPC value? What am I doing wrong here?
C# Code:
string responseStr = new StreamReader(responseStream).ReadToEnd();
responseStream.Flush();
responseStream.Close();
XmlDocument doc = new XmlDocument();
doc.LoadXml(responseStr);
if (doc.GetElementsByTagName("Ack").Item(0).InnerText != "Failure")
{
string UPC = doc.SelectNodes("Item").Item(0).SelectNodes("UPC").Item(0).InnerText;
}
XML Sample:
<?xml version="1.0" encoding="UTF-8"?>
<GetItemResponse xmlns="urn:ebay:apis:eBLBaseComponents">
<Timestamp>2018-07-28T08:18:10.048Z</Timestamp>
<Ack>Success</Ack>
<Version>1069</Version>
<Build>E1069_CORE_API_18748854_R1</Build>
<Item>
<ProductListingDetails>
<ISBN>Not Applicable</ISBN>
<UPC>853365007036</UPC>
<EAN>0853365007036</EAN>
<BrandMPN>
<Brand>UpCart</Brand>
<MPN>MPCB-1DX</MPN>
</BrandMPN>
<IncludeeBayProductDetails>true</IncludeeBayProductDetails>
</ProductListingDetails>
</Item>
</GetItemResponse>
You have a namespace that must be used to get values. Here is the easy way using xml linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
XNamespace ns = doc.Root.GetDefaultNamespace();
string UPC = (string)doc.Descendants(ns + "UPC").FirstOrDefault();
}
}
}
If you have nulls use this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
XNamespace ns = doc.Root.GetDefaultNamespace();
var upcs = doc.Descendants(ns + "UPC");
if (upcs != null)
{
string upc = (string)upcs.FirstOrDefault();
}
}
}
}
I am doing a weather API project. The upcoming 7 days weather information is displaying successfully in message boxes.
Instead of message boxes, how can display all the data with a datagridview?
This is my current working code:
string uri = string.Format("http://api.apixu.com/v1/forecast.xml?key=keygoeshere&q={0}&days=7", city);
XDocument doc = XDocument.Load(uri);
foreach (var npc in doc.Descendants("forecastday"))
{
MessageBox.Show((string)npc.Descendants("date").FirstOrDefault());
MessageBox.Show("Max temp " + (string)npc.Descendants("maxtemp_c").FirstOrDefault());
MessageBox.Show("Min temp " + (string)npc.Descendants("mintemp_c").FirstOrDefault());
MessageBox.Show("Text " + (string)npc.Descendants("text").FirstOrDefault());
MessageBox.Show("Icon " + (string)npc.Descendants("http"+"icon").FirstOrDefault());
}
Put data into a DataTable and then make the DataTable the DataSource of the DGV.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Linq;
using System.Net;
using System.IO;
namespace WindowsFormsApplication3
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
DataTable dt = new DataTable();
dt.Columns.Add("Date", typeof(string));
dt.Columns.Add("Max Temp", typeof(string));
dt.Columns.Add("Min Temp", typeof(string));
dt.Columns.Add("Text", typeof(string));
dt.Columns.Add("Icon", typeof(Bitmap));
string city = "London";
string uri = string.Format("http://api.apixu.com/v1/forecast.xml?key=keygoeshere&q={0}&days=7", city);
XDocument doc = XDocument.Load(uri);
foreach (var npc in doc.Descendants("forecastday"))
{
string iconUri = (string)npc.Descendants("icon").FirstOrDefault();
WebClient client = new WebClient();
byte[] image = client.DownloadData("http:" + iconUri);
MemoryStream stream = new MemoryStream(image);
Bitmap newBitMap = new Bitmap(stream);
dt.Rows.Add(new object[] {
(string)npc.Descendants("date").FirstOrDefault(),
(string)npc.Descendants("maxtemp_c").FirstOrDefault(),
(string)npc.Descendants("mintemp_c").FirstOrDefault(),
(string)npc.Descendants("text").FirstOrDefault(),
newBitMap
});
}
dataGridView1.DataSource = dt;
}
}
}
I recently asked about a piece of code to hold data for my trading cards. I have a file that contains the overall list of the cards in a CSV file. I was wondering if there was any way to remove a row from the CSV file when the card number is selected and the submit button pressed. The code I currently have is:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
namespace YuGiOh_Card_List
{
public partial class frmAddLOB : Form
{
List<string> cardNo = new List<string>();
List<string> cardName = new List<string>();
List<string> cardRarity = new List<string>();
List<string> cardType = new List<string>();
public frmAddLOB()
{
InitializeComponent();
StreamReader reader = File.OpenText("..\\Debug\\lobList.csv");
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(',');
cardNo.Add(values[0]);
cardName.Add(values[1]);
cardRarity.Add(values[2]);
cardType.Add(values[3]);
cboCardNo.Items.Add(values[0]);
}
reader.Close();
}
private void cboCardNo_SelectedIndexChanged(object sender, EventArgs e)
{
lblCardNoFinal.Text = cardNo[cboCardNo.SelectedIndex];
lblCardNameFinal.Text = cardName[cboCardNo.SelectedIndex];
lblCardRarityFinal.Text = cardRarity[cboCardNo.SelectedIndex];
lblCardTypeFinal.Text = cardType[cboCardNo.SelectedIndex];
}
private void btnAdd_Click(object sender, EventArgs e)
{
string file = ("..\\Debug\\LOB.csv");
string delimiter = ",";
var card = new Card(lblCardNoFinal.Text, lblCardNameFinal.Text, lblCardRarityFinal.Text, lblCardTypeFinal.Text);
Global.card.Add(card);
File.AppendAllLines(file, new[] { card.CardNo + delimiter + card.CardName + delimiter + card.CardRarity + delimiter + card.CardType });
MessageBox.Show("Card Added");
}
}
}
So I want the row to be removed from the 'loblist.csv' and added to the LOB file (which it is currently doing). Thanks
This should work (untested). Unfortunately, there's no classes/methods available in .Net (AFAIK) for in-place editing of text files (it makes sense when you think about it I guess). Disclaimer - there are much cleaner ways to do what you're aiming for here functionality-wise, including the approach described by Plutonix above:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
namespace YuGiOh_Card_List
{
public partial class frmAddLOB : Form
{
List<string> cardNo = new List<string>();
List<string> cardName = new List<string>();
List<string> cardRarity = new List<string>();
List<string> cardType = new List<string>();
List<string> Lines = new List<string>();
public frmAddLOB()
{
InitializeComponent();
StreamReader reader = File.OpenText("..\\Debug\\lobList.csv");
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(',');
Lines.Add(line);
cardNo.Add(values[0]);
cardName.Add(values[1]);
cardRarity.Add(values[2]);
cardType.Add(values[3]);
cboCardNo.Items.Add(values[0]);
}
reader.Close();
}
private void cboCardNo_SelectedIndexChanged(object sender, EventArgs e)
{
lblCardNoFinal.Text = cardNo[cboCardNo.SelectedIndex];
lblCardNameFinal.Text = cardName[cboCardNo.SelectedIndex];
lblCardRarityFinal.Text = cardRarity[cboCardNo.SelectedIndex];
lblCardTypeFinal.Text = cardType[cboCardNo.SelectedIndex];
}
private void btnAdd_Click(object sender, EventArgs e)
{
string file = ("..\\Debug\\LOB.csv");
string delimiter = ",";
var card = new Card(lblCardNoFinal.Text, lblCardNameFinal.Text, lblCardRarityFinal.Text,
lblCardTypeFinal.Text);
Global.card.Add(card);
var newLine = card.CardNo + delimiter + card.CardName + delimiter + card.CardRarity + delimiter +
card.CardType;
File.AppendAllLines(file,
new string [] {newLine});
if (Lines.Contains(newLine))
{
Lines.Remove(newLine);
File.WriteAllLines("..\\Debug\\lobList.csv", Lines);
}
MessageBox.Show("Card Added");
}
}
}