I'm getting xml content from a web api. The xml content is a datatable which was converted to xml in the controller and returned as a string.
I try to read it back in a dataset as follows:
var results = response.Content.ReadAsStringAsync().Result;
DataTable dt = new DataTable();
byte[] xmlBytes = Encoding.UTF8.GetBytes(results);
using (DataSet ds = new DataSet())
using (MemoryStream ms = new MemoryStream(xmlBytes))
{
ds.ReadXml(ms);
dt = ds.Tables[0];
}
However is dataset is empty.
The web api controller action does the following:
string xml = string.Empty;
using (DataTable dt = GetResultsAsDataTable())
{
if (dt != null)
{
using (StringWriter sw = new StringWriter())
{
dt.WriteXml(sw, true);
xml = sw.ToString();
}
}
}
The string looks like this:
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/"><DocumentElement>
<tablename>
<id>734</id>
<name>734</name>
</tablename>
</DocumentElement></string>
Is it normal that the xml string looks like this?
Absolutely not.
You should fix results first:
results = System.Web.HttpUtility.HtmlDecode(results);
Then, results will look like this:
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/"><DocumentElement>
<tablename>
<id>734</id>
<name>734</name>
</tablename>
</DocumentElement></string>
I think you shall make your controller action return a datatable object, then the Web API framework will convert it to XML automatically by default, but the XML maybe hard to read.
here is the code I tried,C# Code,returned XML
Related
I have a list as below:
List<datarow> list = getxml_table.AsEnumberable().ToList();
This contains XML DATA in each row. How do I copy this to XML file ? I tried using a XML serializer but it requires a parameterless constructor, so that's not possible.
Any other Ideas.
EDIT:
XML data inside the List<datarow> (this is just a sample for illustration purposes, actual data is quite huge). Each row contains the following XML.
<List>
<Listevent someelementdata ="false">
<someelement>
<moreelement morelementdata = "1234"/>
</someelement>
</Listevent>
</List>
Here is what I tried:
using (stringwriter stringwriter = new stringwriter (new stringbuilder()))
{
xmlserializer xmlserializer = new xmlserializer(typeof(DataRow));
xmlserializer.serialize(stringwriter, list);
var string = stringwriter.string();
}
First of all - DataRow itself does not contains data (at least if we're talking about standard ADO.NET DataRow). Data being stored in concrete "cell" of DataRow (something like DataRow["column_name"]).
Next - why do you need XmlSerializer at all? Maybe I still have not understood your problem completely - but for me it looks like you're having List<DataRow>, and in some cell of each row you're having some string containing xml data.
So you can just write these strings to file something like (pseudocode):
List<DataRow> list = getxml_table.AsEnumberable().ToList();
using (var writer = new StreamWriter(#"c:\temp\1.txt"))
{
foreach(var row in list)
{
writer.WriteLine(row["column_name"]);
}
}
I want to remove this xmlns="http://www.AB.com/BC/QualityDeviationCase/1_0" from all xml element except root tag. xml element using C#. I have written below code to get to as xml form. But unable to remove xmlns tag from xml element.
<?xml version="1.0" encoding="utf-16"?>
<QualityDeviationCaseType xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<CaseID xmlns="http://www.AB.com/BC/QualityDeviationCase/1_0">2</CaseID>
<Description xmlns="http://www.AB.com/BC/QualityDeviationCase/1_0">Air filter is not present</Description>
<StartDate xmlns="http://www.AB.com/BC/QualityDeviationCase/1_0">0001-01-01T00:00:00</StartDate>
<LastUpdated xmlns="http://www.AB.com/BC/QualityDeviationCase/1_0">0001-01-01T00:00:00</LastUpdated>
</QualityDeviationCaseType>
After remove xmlns="http://www.AB.com/BC/QualityDeviationCase/1_0" this tag, my result should return like this as below-
<?xml version="1.0" encoding="utf-16"?>
<QualityDeviationCaseType xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<CaseID>2</CaseID>
<Description>Air filter is not present</Description>
<StartDate>0001-01-01T00:00:00</StartDate>
<LastUpdated>0001-01-01T00:00:00</LastUpdated>
</QualityDeviationCaseType>
My C# Code, I am getting xml result from my XSD file.
connection.Open();
adapter = new SqlDataAdapter(sql, connection);
adapter.Fill(dt);
myTestTable = dt.Clone();
DataRow[] orderRows = dt.Select();
XmlDocument xmlDoc = new XmlDocument();
QualityDeviationCaseType oQualityDeviationCaseType = new QualityDeviationCaseType();
foreach (DataRow row in orderRows)
{
oQualityDeviationCaseType = new QualityDeviationCaseType();
oQualityDeviationCaseType.CaseID = row[0].ToString();
oQualityDeviationCaseType.Description = row[3].ToString();
}
using (StringWriter stringwriter = new System.IO.StringWriter())
{
XmlSerializer ser = new XmlSerializer(typeof(QualityDeviationCaseType));
ser.Serialize(stringwriter, oQualityDeviationCaseType);
sampleChannel.Publish(stringwriter.ToString());
//This line of code sending my xml file to IBM WMQ.
}
As per my above code, My result is coming with xml tag for each lement. I want to remove from element tag using c#.
The xmlns attribute has important semantics in XML: it puts all elements in the default namespace http://www.AB.com/BC/QualityDeviationCase/1_0.
I am not familiar with C# specifically, however: removing it implies reasoning at the semantic level rather than syntactic.
Concretely, it should be done by removing the namespace of all elements in the XML document being exported, or not putting them in any namespace in the first place. If the C# library is complete, it should provide a way to do so.
Did you try Regex?
using System.Text.RegularExpressions;
...
string pattern = #"xmlns=""[a-zA-Z0-9:\/._]{1,}""";
using (StringWriter stringwriter = new System.IO.StringWriter())
{
XmlSerializer ser = new XmlSerializer(typeof(QualityDeviationCaseType));
ser.Serialize(stringwriter, oQualityDeviationCaseType);
string s = stringwriter.ToString();
Match m = Regex.Match(s,pattern);
if(m.Success)
s=s.Replace(m.Value, "");
sampleChannel.Publish(s);
//This line of code sending my xml file to IBM WMQ.
}
I'm not that familiar with XmlSerializer, but that should work I think. Match will only find anything beginning with 'xmlns="' and ending with '"'.
I have this xml file with several levels for node's childs:
-product
--name
--price
--made
-----product
--------name
--distributor
-----name
------address
/product
I need to read it in sequence, but it's not possible with XmlReader, so I have to use XmlDocument to read each node and copy into DataSet (or similar).
How can I read node by node and copy to dataset in C# ??? Any help please?
Convert xml string to DataSet using StringReader
string xmlData = "<product><name></name><price></price><made></made></product>";
StringReader reader = new StringReader(xmlData);
DataSet ds = new DataSet();
ds.ReadXml(reader);
Write XML Data into a DataSet directly from xml file:
string myfile = #"C:\myXml.xml";
DataSet ds = new DataSet();
ds.ReadXml(myfile);
I think you can use Xpath over XMl Document to read node by node.
It is possible using XDocument and LINQ-to-XML:
XDocument doc = XDocument.Load("test.xml");
// Create two DataTable instances.
DataTable table1 = new DataTable("patients");
table1.Columns.Add("name");
foreach(var name in doc.Root.DescendantNodes().OfType<XElement>()
.Select(x => x.Name).Distinct())
{
table1.Rows.Add(name);
Console.WriteLine(name);
}
My xml
<?xml version="1.0" encoding="utf-8" ?>
<Category>
<Youth>
</Youth>
<GeneralStores>
</GeneralStores>
<Schools>
</Schools>
<Colleges>
</Colleges>
<GovernmentOffices>
</GovernmentOffices>
<Restaurants>
</Restaurants>
<MovieTheatres>
</MovieTheatres>
</Category>
I need data table like
_______________________
Category
__________
Youth
GeneralStores
Schools
Colleges
GovernmentOffices
Restaurants
MovieTheatres
I am binding this datatable to telrik rad grid on need datasource event
here is my .cs code
protected void CategoriesRadGrid_NeedDataSource(object source, Telerik.Web.UI.GridNeedDataSourceEventArgs e)
{
try
{
//create the DataTable that will hold the data
DataTable CategoryDT = new DataTable("MainCategory");
CategoryDT.Columns.Add("Category", System.Type.GetType("System.String"));
CategoryDT.ReadXml(#"C:\Users\MyID\Documents\Visual Studio 2010\Projects\SomeName\InfoXML\XMLCategory.xml");
}
catch (Exception ex)
{
}
}
Code executes good with no data in data table.
Also tell me How to give file location when file is on servers?
presently I am using my local machine path where the file is located.
use XmlDocument to read your XML
XmlDocument doc= new XmlDocument();
doc.Load("physical path to file.xml");
// doc.LoadXml(stringXml);
DataTable dt = new DataTable();
if(doc.ChildNodes[1]!=null)
dt.Columns.Add(doc.ChildNodes[1].Name); //Assuming you want the rood node to be the only column of the datatable
//iterate through all the childnodes of your root i.e. Category
foreach(XmlNode node in doc.ChildNodes [1].ChildNodes )
{
dt.Rows.Add(node.Name);
}
Try the following:
private static DataTable BuildDataTable(XElement x)
{
DataTable dt = new DataTable();
dt.Columns.Add(new DataColumn(x.Name.ToString()));
foreach (var d in x.Descendants())
{
DataRow drow = dt.NewRow();
drow[0] = d.Value;
dt.Rows.Add(drow);
}
return dt;
}
the method will iterate through the xml and create the dataTable. Xelement is part linq and will require .Net framework 4. It represents an XML element.
To call the method :
//this answers your second question,
//use Server.MapPath to find your file.
XElement x = XElement.Load(Server.MapPath(".") + #"\test.xml");
DataTable dt = BuildDataTable(x);
I am using following code to get List from xml file -
public static List<T> GetListFromXml<T>(string filePath)
{
using (TextReader reader = new StreamReader(filePath))
{
XmlSerializer serializer = new XmlSerializer(typeof(List<T>));
return (List<T>) serializer.Deserialize(reader);
}
}
However, I also need a way of filtering records where I can filter list by -
- no. of records to take from xml file
- filter by a particular node value
So signature of above method will change to -
public static List<T> GetListFromXml<T>(string filePath,
int listCount,
string filterbyNode,
string filterByValue);
Please guide me if I can filter directly from XML file or I should filter from returned list?
P.S.
The xml file mentioned above is also created from code using -
public static void WriteListToXml<T>(List<T> list, string filePath)
{
using (TextWriter writer = new StreamWriter(filePath))
{
XmlSerializer serializer = new XmlSerializer(typeof(List<T>));
serializer.Serialize(writer, list);
}
}
Why I am saving my custom collection returned from database to xml file - because I want to process only a batch of records at a time.
and XML file snippet (generated from above code) -
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfClassifiedLocation xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<CLocation>
<CId>5726</CId>
<Long>0</Long>
<Lat>0</Lat>
<Postcode>ZZ1 5ZZ</Postcode>
<Street />
<Town />
</CLocation>
<CLocation>
<CId>5736</CId>
<Long>0</Long>
<Lat>0</Lat>
<Postcode>ZZ1 5ZZ</Postcode>
<Street />
<Town />
</CLocation>
</ArrayOfClassifiedLocation>
If you have access to .net >= 3.5, you should consider using Linq to Xml
Below an example of LINQ-to-XML query which consider cid paremeter filter. If you put empty string in cidFilter the query would return all entries:
// you can use Parse() method:
// XDocument loaded = XDocument.Parse(xmlString);
XDocument loaded = XDocument.Load("c:\\temp\\testxl.xml");
// return only entry fith CID == 5726
string cidFilter = "5726";
var filteredItems =
loaded.Descendants("CLocation")
.Select((w, i) =>
new
{
Index = i,
CID = w.Descendants("CId").FirstOrDefault().Value,
PostCode = w.Descendants("Postcode").FirstOrDefault().Value
})
.Where(item => String.IsNullOrEmpty(cidFilter) || item.CID == cidFilter)
.ToList();
int itemsCount = filteredItems.Count();