Issues with retrieving data from xml - c#

So I'm trying to retrieve the subscriber count from this xml file but I'm having an issue getting the data. Currently I'm using doc.DocumentElement.SelectSingleNode for each level but I'm not having much luck and as I'm not very familiar with C# xml I dont really know what my issue is. Any help would be much appreciated and the xml is attached below.
I am trying to get the data from the subscriberCount and my current code is attatched at the bottom, although it doesn't work
-Max
<?xml version="1.0" encoding="UTF-8"?>
<Root>
<kind>youtube#channelListResponse</kind>
<etag>"xxx"</etag>
<pageInfo>
<totalResults>1</totalResults>
<resultsPerPage>1</resultsPerPage>
</pageInfo>
<items>
<kind>youtube#channel</kind>
<etag>"xxx"</etag>
<id>xxx</id>
<statistics>
<viewCount>0</viewCount>
<commentCount>0</commentCount>
<subscriberCount>200</subscriberCount>
<hiddenSubscriberCount>false</hiddenSubscriberCount>
<videoCount>5</videoCount>
</statistics>
</items>
</Root>
string totalSubs = doc.DocumentElement.SelectSingleNode("Root").SelectSingleNode("items").SelectSingleNode("statistics").SelectSingleNode("subscriberCount").Value;

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);
XElement root = doc.Root;
Response response = new Response();
response.kind = (string)root.Element("kind");
response.etag = (string)root.Element("etag");
response.totalResults = (int)root.Descendants("totalResults").FirstOrDefault();
response.resultsPerPage = (int)root.Descendants("resultsPerPage").FirstOrDefault();
XElement items = root.Element("items");
response.itemKind = (string)items.Element("kind");
response.itemEtag = (string)items.Element("etag");
response.id = (string)items.Element("id");
XElement statistics = items.Element("statistics");
response.viewCount = (int)statistics.Element("viewCount");
response.commentCount = (int)statistics.Element("commentCount");
response.subscriberCount = (int)statistics.Element("subscriberCount");
response.hiddenSubscriberCount = (Boolean)statistics.Element("hiddenSubscriberCount");
response.videoCount = (int)statistics.Element("videoCount");
}
}
public class Response
{
public string kind { get; set; }
public string etag { get; set; }
public int totalResults { get; set; }
public int resultsPerPage { get; set; }
public string itemKind { get; set; }
public string itemEtag { get; set; }
public string id { get; set; }
public int viewCount { get; set; }
public int commentCount { get; set; }
public int subscriberCount { get; set; }
public Boolean hiddenSubscriberCount { get; set; }
public int videoCount { get; set; }
}
}

Related

XML deserialization to object

So i've been trying to deserialize this xml file to some objects, its simple enough but it keeps returning null to the objects, the data that i need is stored inside the attributes of the element.
Here is the XML.
<exchangerates xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" type="Valutakurser" author="Danmarks Nationalbank" refcur="DKK" refamt="1">
<dailyrates id="2020-10-20">
<currency code="AUD" desc="Australske dollar" rate="442,98"/>
<currency code="BGN" desc="Bulgarske lev" rate="380,53"/>
</dailyrates>
And this is the deserialisation code.
public static T DeserializeElement<T>(string filename)
{
try
{
T result;
XmlSerializer serializer = new XmlSerializer(typeof(T), new
XmlRootAttribute("exchangerates"));
using (TextReader tr = new StringReader(filename))
{
result = (T)serializer.Deserialize(tr);
}
return result;
}
catch { throw; }
}
And these are the objects
[XmlRoot(Namespace = "http://www.w3.org/2001/XMLSchema-instance",
ElementName = "exchangerates",
DataType = "Valutakurser")]
[Serializable]
public class Valutakurser
{
[XmlArray("dailyrates")]
public DateTime Id { get; set; }
public Currency Currency { get; set; }
}
[Serializable]
public class Currency
{
public string Code { get; set; }
public string Desc { get; set; }
public double Rate { get; set; }
public Currency() { }
}
Currently I keep getting this error and everything returned null:
InvalidOperationException: For non-array types, you may use the following attributes: XmlAttribute, XmlText, XmlElement, or XmlAnyElement
Try following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create(FILENAME);
XmlSerializer serializer = new XmlSerializer(typeof(Valutakurser));
Valutakurser valutakurser = (Valutakurser)serializer.Deserialize(reader);
}
}
[XmlRoot(ElementName = "exchangerates")]
public class Valutakurser
{
[XmlAttribute]
public DateTime id { get; set; }
[XmlElement("dailyrates")]
public DailyRates DalyRates { get; set; }
}
public class DailyRates
{
[XmlElement("currency")]
public List<Currency> Currency { get; set; }
}
public class Currency
{
[XmlAttribute]
public string code { get; set; }
[XmlAttribute]
public string desc { get; set; }
[XmlAttribute]
public double rate { get; set; }
public Currency() { }
}
}

Issues Deserializing Xml in C#

I'm following the tutorial given here for deserializing an embedded xml document.
My Xml doc:
<?xml version="1.0" encoding="utf-8" ?>
<ArrayOfAgency xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<DbAgencyDefinition>
<Name>RTD</Name>
<Country>USA</Country>
<City>Denver</City>
<State>CO</State>
<GtfsZipUrlDirectory>http://www.address.com/etc/</GtfsZipUrlDirectory>
<GtfsZipUrlFileName>file_name.zip</GtfsZipUrlFileName>
</DbAgencyDefinition>
</ArrayOfAgency>
My class I'm deserializing to:
public class DbAgencyDefinition
{
public string Name { get; set; }
public string City { get; set; }
public string Country { get; set; }
public string GtfsZipUrlDirectory { get; set; }
public string GtfsZipUrlFileName { get; set; }
public string State { get; set; }
}
The code that's trying to deserialize the XML to a list of DbAgencyDefinition:
var assembly = IntrospectionExtensions.GetTypeInfo(typeof(DbAgencyDefinition)).Assembly;
Stream stream = assembly.GetManifestResourceStream("MyNamespace.Resources.xml.AgencyDefinitions.xml");
var agencies = new List<DbAgencyDefinition>();
using (var reader = new StreamReader(stream))
{
var serializer = new XmlSerializer(typeof(List<DbAgencyDefinition>));
agencies = (List<DbAgencyDefinition>)serializer.Deserialize(reader);
}
The error I'm getting is:
System.Exception: There is an error in XML document. <ArrayOfAgency xmlns=''> was not expected
I've tried a million things with the XML, marking the class as Serializable, and it always returns this error. I looked at the code samples that the tutorial gives and I can't figure out why I'm getting this error.
VS for Windows, and maybe on Mac as well, has a special tool that will convert copied Xml into autogenerated classes. Now, it's not perfect but if you take your Xml file it generates a couple of classes similar to this:
public class ArrayOfAgency
{
public ArrayOfAgencyDbAgencyDefinition DbAgencyDefinition { get; set; }
}
public class ArrayOfAgencyDbAgencyDefinition
{
public string Name { get; set; }
public string Country { get; set; }
public string City { get; set; }
public string State { get; set; }
public string GtfsZipUrlDirectory { get; set; }
public string GtfsZipUrlFileName { get; set; }
}
As you might notice ArrayOfAgency is determined as a class holding a DbAgencyDefinition, which is why it's throwing an error while trying to deserialize it directly into a List<DbAgencyDefinition>. The type and what the serializer is expecting are not quite the same.
var serializer = new XmlSerializer(typeof(ArrayOfAgency));
var agencies = ((ArrayOfAgency)serializer.Deserialize(reader)).DbAgencyDefinition;
Also, as I mentioned the auto-generation may not be perfect because ArrayOfAgency may need to hold an array instead of a direct class if there can be more than one DbAgencyDefinition possible in Xml.
public class ArrayOfAgency
{
public ArrayOfAgencyDbAgencyDefinition[] DbAgencyDefinition { get; set; }
}
If you need more help or info on Xml Serialization check out the docs.
Try following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
namespace ConsoleApplication120
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
using (var reader = new StreamReader(FILENAME, Encoding.UTF8))
{
var serializer = new XmlSerializer(typeof(ArrayOfAgency));
ArrayOfAgency agencies = (ArrayOfAgency)serializer.Deserialize(reader);
}
}
}
public class ArrayOfAgency
{
public DbAgencyDefinition DbAgencyDefinition { get; set; }
}
public class DbAgencyDefinition
{
public string Name { get; set; }
public string City { get; set; }
public string Country { get; set; }
public string GtfsZipUrlDirectory { get; set; }
public string GtfsZipUrlFileName { get; set; }
public string State { get; set; }
}
}

How to return nested xml from web service

I am generating below xml from SQL stored procedure and I want to return the same from web service method. when I tried to read in to dataset and return it its displaying whole thing as one string.
<HrDetails EmployeeLastName="NEUHAUS" EmployeeFirstName="abc" EmployeeID="00182838" ID="45685325" OrganizationCode="H2254" Division="hhs" OfficialPositionTitle="CLINICAL FELLOW" OccupationalSeries="0602" AnualPay="124000.0000">
<abcs>
<abc>
<Amount>0.00</Amount>
<Date>08/07/2018</Date>
</abc>
</abcs>
<xyzs>
<xyz>
<Amount>0</Amount>
<Date>07/01/2018</Date>
</xyz>
<xyz>
<Amount>0</Amount>
<Date>01/07/2018</Date>
</xyz>
<xyz>
<Amount>0</Amount>
<Date>08/07/2018</Date>
</xyz>
</xyzs>
</HrDetails>
Thanks in advance.
Using xml linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
string response = File.ReadAllText(FILENAME);
XDocument doc = XDocument.Parse(response);
XElement hrDetails = doc.Root;
HR hr = new HR()
{
employeeLastName = (string)hrDetails.Attribute("EmployeeLastName"),
employeeFirstName = (string)hrDetails.Attribute("EmployeeFirstName"),
employeeID = (string)hrDetails.Attribute("EmployeeID"),
id = (string)hrDetails.Attribute("ID"),
organizationCode = (string)hrDetails.Attribute("OrganizationCode"),
division = (string)hrDetails.Attribute("Division"),
officialPositionTitle = (string)hrDetails.Attribute("OfficialPositionTitle"),
occupationalSeries = (string)hrDetails.Attribute("OccupationalSeries"),
anualPay = (decimal)hrDetails.Attribute("AnualPay")
};
hr.accounts = hrDetails.Elements().Select(x => new Accounts() {
name = x.Name.LocalName, accounts = x.Elements().Select(y => new Account() {
name = y.Name.LocalName,
amount = (decimal)y.Element("Amount"),
date = (DateTime)y.Element("Date")
}).ToList()
}).ToList();
}
}
public class HR
{
public string employeeLastName { get; set;}
public string employeeFirstName { get; set;}
public string employeeID { get; set;}
public string id { get; set;}
public string organizationCode { get; set;}
public string division { get; set;}
public string officialPositionTitle { get; set;}
public string occupationalSeries { get; set;}
public decimal anualPay { get; set;}
public List<Accounts> accounts { get; set; }
}
public class Accounts
{
public string name { get; set; }
public List<Account> accounts { get; set; }
}
public class Account
{
public string name { get; set; }
public decimal amount { get; set; }
public DateTime date { get; set; }
}
}

Write List<object> to XML file with elements and attribute

I have the following class:
[XmlType("supervisor")]
public class Supervisor
{
[XmlAttribute("id")]
public string Id { set; get; }
[XmlElement("Name")]
public string Name { set; get; }
[XmlElement("Contract")]
public int Contracts { set; get; }
[XmlElement("Volume")]
public long Volume { set; get; }
[XmlElement("Average")]
public int Average { set; get; }
}
which reads from XML file:
<digital-sales xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<supervisor id="1236674">
<Name>Hiroki</Name>
<Contract>11</Contract>
<Volume>1036253</Volume>
<Average>94205</Average>
</supervisor>
<supervisor id="123459">
<Name>Ayumi</Name>
<Contract>5</Contract>
<Volume>626038</Volume>
<Average>125208</Average>
</supervisor> ...
</digital-sales>
in the code I create List and process it.
now I want to write the List to XML file while maintaining the
same XML structure. How do I do that?
How to use xml id to fill class object?
Here is the code :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication98
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create(FILENAME);
XmlSerializer serializer = new XmlSerializer(typeof(DigitalSales));
DigitalSales digitalSales = (DigitalSales)serializer.Deserialize(reader);
reader.Close();
XmlWriter writer = XmlWriter.Create(FILENAME);
serializer.Serialize(writer, digitalSales);
}
}
[XmlRoot("digital-sales")]
public class DigitalSales
{
[XmlElement("supervisor")]
public List<Supervisor> supervisor { get; set; }
}
[XmlRoot("supervisor")]
public class Supervisor
{
[XmlAttribute("id")]
public string Id { set; get; }
[XmlElement("Name")]
public string Name { set; get; }
[XmlElement("Contract")]
public int Contracts { set; get; }
[XmlElement("Volume")]
public long Volume { set; get; }
[XmlElement("Average")]
public int Average { set; get; }
}
}

XML conversion to Json and DeserializeObject issue - InfoPath namespaces?

I am looking into loading a large number of InfoPath XML files into Cosmos DB as Json files to test a possible project. But I am struggling with converting the XML files to Json and then loading back into a c# class. I think this is related to the namespace that InfoPath puts into the XML but I'm not sure. I thought at first I should try to remove all the namespace references from the XML but now I'm wondering if I just need to work more on the definition of the class file. To generate the class file I used Visual Studio "paste as Json". I assumed after loading the XML, saving to Json, then using that as the basis for the new class file, I could load right back into the object but when I call DeserializeObject it always ends up null.
Is this because the class file definition needs to be changed or should I instead look to try and clean the XML prior to converting to Json?
Sample XML
<?xml version="1.0" encoding="utf-8"?>
<?mso-infoPathSolution name="urn:schemas-microsoft-com:office:infopath:myProject:-myXSD-2017-05-05T14-19-13" solutionVersion="1.0.0.2046" productVersion="16.0.0.0" PIVersion="1.0.0.0" href="https://myportal.sharepoint.com/sites/mySite/myProject/Forms/template.xsn"?>
<?mso-application progid="InfoPath.Document" versionProgid="InfoPath.Document.4"?>
<?mso-infoPath-file-attachment-present?>
<my:myFields xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2017-05-05T14:19:13" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:pc="http://schemas.microsoft.com/office/infopath/2007/PartnerControls" xmlns:ma="http://schemas.microsoft.com/office/2009/metadata/properties/metaAttributes" xmlns:d="http://schemas.microsoft.com/office/infopath/2009/WSSList/dataFields" xmlns:q="http://schemas.microsoft.com/office/infopath/2009/WSSList/queryFields" xmlns:dfs="http://schemas.microsoft.com/office/infopath/2003/dataFormSolution" xmlns:dms="http://schemas.microsoft.com/office/2009/documentManagement/types" xmlns:tns="http://microsoft.com/webservices/SharePointPortalServer/UserProfileService" xmlns:s1="http://microsoft.com/wsdl/types/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xd="http://schemas.microsoft.com/office/infopath/2003" xml:lang="en-US">
<my:Admin>
<my:Routing_Order>
<my:Approver-1_Order>1</my:Approver-1_Order>
<my:Approver-2_Order>5</my:Approver-2_Order>
<my:Approver-3_Order>4</my:Approver-3_Order>
</my:Routing_Order>
</my:Admin>
<my:Request_Status>Save as Draft</my:Request_Status>
<my:Request_Type>CAPEX</my:Request_Type>
</my:myFields>
Class file
namespace xml_to_json
{
public class Rootobject
{
public MyMyfields mymyFields { get; set; }
}
public class MyMyfields
{
public string xmlnsmy { get; set; }
public string xmlnsxsi { get; set; }
public string xmlnsxhtml { get; set; }
public string xmlnspc { get; set; }
public string xmlnsma { get; set; }
public string xmlnsd { get; set; }
public string xmlnsq { get; set; }
public string xmlnsdfs { get; set; }
public string xmlnsdms { get; set; }
public string xmlnstns { get; set; }
public string xmlnss1 { get; set; }
public string xmlnshttp { get; set; }
public string xmlnstm { get; set; }
public string xmlnssoap { get; set; }
public string xmlnssoapenc { get; set; }
public string xmlnsmime { get; set; }
public string xmlnssoap12 { get; set; }
public string xmlnswsdl { get; set; }
public string xmlnsxd { get; set; }
public string xmllang { get; set; }
public MyAdmin myAdmin { get; set; }
public string myRequest_Status { get; set; }
public string myRequest_Type { get; set; }
}
public class MyAdmin
{
public MyRouting_Order myRouting_Order { get; set; }
}
public class MyRouting_Order
{
public string myApprover1_Order { get; set; }
public string myApprover2_Order { get; set; }
public string myApprover3_Order { get; set; }
}
}
Console test code
namespace xml_to_json
{
class Program
{
static void Main(string[] args)
{
XmlDocument myDoc = new XmlDocument();
string sourcedir = #"C:\Users\mystuff\Downloads\test-clean\";
string xmlfilein = #"test";
string xmlfile = string.Concat(sourcedir, xmlfilein, ".xml");
string jsonfileout = string.Concat(sourcedir, xmlfilein, ".json");
myDoc.Load(xmlfile);
string jsonText = JsonConvert.SerializeXmlNode(myDoc.LastChild);
File.WriteAllText(jsonfileout, jsonText);
Rootobject obj = new Rootobject();
obj = JsonConvert.DeserializeObject<Rootobject>(jsonText);
Console.WriteLine(obj.mymyFields.myRequest_Status);
}
}
}
Try code below 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);
XElement routingOrder = doc.Descendants().Where(x => x.Name.LocalName == "Routing_Order").FirstOrDefault();
Dictionary<string, string> orders = routingOrder.Elements()
.GroupBy(x => x.Name.LocalName, y => (string)y)
.ToDictionary(x => x.Key, y => y.FirstOrDefault());
string status = (string)doc.Descendants().Where(x => x.Name.LocalName == "Request_Status").FirstOrDefault();
string requestType = (string)doc.Descendants().Where(x => x.Name.LocalName == "Request_Type").FirstOrDefault();
}
}
}
Using suggestion from jdweng and XDocument helped to clean the XML file for easier transition to Json. Below is a sample of code I used to clean the document.
XDocument newxdoc = XDocument.Load(xmlfile);
newxdoc.DescendantNodes().Where(e => e.NodeType.ToString().StartsWith("ProcessingInstruction")).Remove();
string newstringdoc = RemoveAllNamespaces(newxdoc.ToString());
newxdoc = XDocument.Parse(newstringdoc);

Categories

Resources