I'm pulling an XML-Sitemap from a website to parse it.
The easyest way would be to deserialize it into on objet.
I get throw the error "Error in XML-Document" on the last line in my example-code. Does anybody know why. There aren't any more details in the error-message.
My Code so far:
[Serializable, XmlRoot("urlset")]
public class Urlset
{
public B5_Url[] urls;
}
[XmlType("url")]
public class B5_Url
{
[XmlElement("loc")]
public string loc;
[XmlElement("lastmod")]
public string lastmod;
[XmlElement("changefreq")]
public string changefreq;
}
class Program
{
static void Main(string[] args)
{
string url = "http://www.myurl.de/sitemap.xml";
XmlSerializer ser = new XmlSerializer(typeof(Urlset));
WebClient client = new WebClient();
string data = Encoding.Default.GetString(client.DownloadData(url));
Stream stream = new MemoryStream(Encoding.UTF8.GetBytes(data));
Urlset reply = (Urlset)ser.Deserialize(stream);
}
}
This is the XML:
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
<url>
<loc>http://www.myurl.de/</loc>
<lastmod>2012-06-25T17:10:30+00:00</lastmod>
<changefreq>always</changefreq>
</url>
</urlset>
Thanks for your help :)
You should do what #vitalygolub is suggesting. Also, you will still get an error because of Namespace set in the root element. To fix it:
[XmlRoot("urlset", Namespace="http://www.sitemaps.org/schemas/sitemap/0.9")]
public class Urlset
{
[XmlElement("url")]
public B5_Url[] urlset;
}
public class B5_Url
{
[XmlElement("loc")]
public string loc;
[XmlElement("lastmod")]
public string lastmod;
[XmlElement("changefreq")]
public string changefreq;
}
I tested this code and it works with your input.
If that is your XML, you're missing a closing </url>:
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
<url>
<loc>http://www.myurl.de/</loc>
<lastmod>2012-06-25T17:10:30+00:00</lastmod>
<changefreq>always</changefreq>
</url>
</urlset>
I got the error <urlset xmlns='http://www.sitemaps.org/schemas/sitemap/0.9'> was not expected.
Changing:
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
To
<urlset>
Made it not error.
This is my working linqpad example
[Serializable, System.Xml.Serialization.XmlRoot("urlset")]
public class Urlset
{
[System.Xml.Serialization.XmlElement("url")]
public B5_Url[] urls;
}
[System.Xml.Serialization.XmlType("url")]
public class B5_Url
{
[System.Xml.Serialization.XmlElement("loc")]
public string loc;
[System.Xml.Serialization.XmlElement("lastmod")]
public string lastmod;
[System.Xml.Serialization.XmlElement("changefreq")]
public string changefreq;
}
class Program
{
static void Main(string[] args)
{
var data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><urlset><url><loc>http://www.myurl.de/</loc><lastmod>2012-06-25T17:10:30+00:00</lastmod><changefreq>always</changefreq></url></urlset>";
var ser = new System.Xml.Serialization.XmlSerializer(typeof(Urlset));
Stream stream = new MemoryStream(Encoding.UTF8.GetBytes(data));
Urlset reply = (Urlset)ser.Deserialize(stream);
reply.Dump();
}
}
The other change I had to make was the [System.Xml.Serialization.XmlElement("url")] attribute on the B5_Url[] array in UrlSet
You have to provide the following
[Serializable, XmlRoot("urlset")]
public class Urlset
{
[XmlElement("url")]
public B5_Url[] urls;
}
Which will serialize every element in a collection directly into your root-element instead of an urls-element.
EDIT: You can however omit the XmlType-attribute from B5_Url.
It is probably because your classes will be serialized as this xml
<?xml version="1.0"?>
<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<urls>
<url>
<loc>http://www.myurl.de/</loc>
<lastmod>2012-06-25T17:10:30+00:00</lastmod>
<changefreq>always</changefreq>
</url>
</urls>
</urlset>
Try change like this
[Serializable, XmlRoot("urlset")]
public class Urlset
{
[XmlElement("urlset") ] //should be here
public B5_Url[] urls;
}
[XmlType("url")]
public class B5_Url
{
[XmlElement("loc")]
public string loc;
[XmlElement("lastmod")]
public string lastmod;
[XmlElement("changefreq")]
public string changefreq;
}
Related
I need to deserialize XML file to an object in C#:
<?xml version="1.0" encoding="utf-16"?>
<Test xmlns:xsd=http://www.w3.org/2001/XMLSchema xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance>
<Number>110658419900</Number>
<WorkorderName>2103477915XVN35S_FR_LEFTX111</WorkorderName>
<RequestDate>2022-10-13T16:53:13.2171314+02:00</RequestDate>
<ShelfNumber>4</ShelfNumber>
</Test>
public class Test
{
public string Number { get; set; }
public string WorkorderName { get; set; }
public string RequestDate { get; set; }
public string ShelfNumber { get; set; }
}
I am using this approach:
try
{
XmlSerializer serializer = new XmlSerializer(typeof(Test));
StreamReader reader = new StreamReader(fileSystemEventArgs.FullPath);
Test test = (Test)serializer.Deserialize(reader);
reader.Close();
return test;
}
catch (Exception ex)
{
string message = ex.Message;
}
But I am receiving an error:
{"There is an error in XML document (2, 17)."}
Everything is working If I remove this from XML:
xmlns:xsd=http://www.w3.org/2001/XMLSchema xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance
I don't know why this is happening. How to solve this issue? How to ignore this xmls:xsd and xmls:xsi?
That "xml" isn't valid xml, and the parser is correct to shout here. The xml should start (note the quotes):
<Test xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
(etc)
However, those are just namespace alias declarations, and those aliases are never used, so: you can also just delete them here, leaving your xml as starting
<Test>
I need some help regarding deserialization of this kind of xml in C#:
<Request>
<AccountStage att1="419749" att2="575474" att3="800177" att4="096057" att5="917185" att6="017585" att7="huKuBgcQ" att8="stgs10" att9="ACTIVE" att10="2" att11="2"/>
</Request>
If I use the "Special paste" feature from VS, and convert the request as xml classes, when I want to use the request and send it to the server, it changes the format as follows:
<Request>
<AccountStage>
<att1>22222</att1>
<att2>22222</att2>
<att3>22222</att3>
<att4>2</att4>
<att5>2</att5>
<att6>22222</att6>
<att7>Ion</att7>
<att8>agg3</att8>
<att9>ACTIVE</att9>
<att10>2</att10>
<att11>2</att11>
</AccountStage>
</Request>
Use XmlAttribute to specify how members should be defined/interpreted:
using System.IO;
using System.Xml.Serialization;
namespace WpfApp2
{
internal class Test
{
private readonly string xml = #"<?xml version=""1.0"" encoding=""utf-8""?>
<Request>
<AccountStage att1=""419749"" att2=""575474"" att3=""800177"" att4=""096057"" att5=""917185"" att6=""017585"" att7=""huKuBgcQ""
att8=""stgs10"" att9=""ACTIVE"" att10=""2"" att11=""2"" />
</Request>";
public Test()
{
Request request;
// serialize
var serializer = new XmlSerializer(typeof(Request));
using (var reader = new StringReader(xml))
{
request = (Request) serializer.Deserialize(reader);
}
// deserialize
request.AccountStage.Attribute1 = "abcd";
using (var writer = new StringWriter())
{
serializer.Serialize(writer, request);
var s = writer.ToString();
}
}
}
public class Request
{
public AccountStage AccountStage { get; set; }
}
public class AccountStage
{
[XmlAttribute("att1")]
public string Attribute1 { get; set; }
}
}
Result
<?xml version="1.0" encoding="utf-16"?>
<Request xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<AccountStage att1="abcd" />
</Request>
While creating xml from C# class I getting some default namespaces(xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema") in root tag (Order) like below. but, I want to remove those default namespaces and I need the following namespace in the root tag (Order xmlns="http://example.com/xml/1.0").
how to remove those default namespaces and replace in c# code. thanks in advance.
<?xml version="1.0"?>
<Order xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Number Type="mobile">9999999999</Number>
<TrackStartDateTime>2015-05-30 11:00 ET</TrackStartDateTime>
<Notifications>
<Notification>
<PartnerMPID>99999999</PartnerMPID>
<IDNumber>L563645</IDNumber>
<TrackDurationInHours>120</TrackDurationInHours>
<TrackIntervalInMinutes>240</TrackIntervalInMinutes>
</Notification>
</Notifications>
<Carrier>
<Dispatcher>
<DispatcherName>?</DispatcherName>
<DispatcherPhone>0</DispatcherPhone>
<DispatcherEmail>?</DispatcherEmail>
</Dispatcher>
</Carrier>
</Order>
I have used following C# classes.
[XmlRoot("Order")]
public class Order
{
[XmlElement("Number")]
public Number Number;
[XmlElement("TrackStartDateTime")]
public string TrackStartDateTime;//TODO - need to check
[XmlElement("Notifications")]
public Notifications Notifications;//TODO - notification tag should come inside Notifications tag
[XmlElement("Carrier")]
public Carrier Carrier;
public Order() {
Number = new Number();
Notifications = new Notifications();
Carrier = new Carrier();
TripSheet = new TripSheet();
}
}
public class Number
{
[XmlAttribute("Type")]
public string Type;
[XmlText]
public Int64 Value;
}
public class Notifications {
[XmlElement("Notification")]
public List<Notification> Notification;
public Notifications() {
Notification = new List<Notification>();
}
}
public class Notification
{
[XmlElement("PartnerMPID")]
public string PartnerMPID { get; set; }
[XmlElement("IDNumber")]
public string IDNumber { get; set; }
[XmlElement("TrackDurationInHours")]
public int TrackDurationInHours { get; set; }
[XmlElement("TrackIntervalInMinutes")]
public int TrackIntervalInMinutes { get; set; }
}
public class Carrier
{
[XmlElement("Name")]
public string Name;
[XmlElement("Dispatcher")]
public Dispatcher Dispatcher;
public Carrier() {
Dispatcher = new Dispatcher();
}
}
public class Dispatcher
{
[XmlElement("DispatcherName")]
public string DispatcherName;
[XmlElement("DispatcherPhone")]
public Int64 DispatcherPhone;
[XmlElement("DispatcherEmail")]
public string DispatcherEmail;//conform format for email
}
and I have taken the new instance of Order Class and for testing purpose, I have hard-coded values for the each fields and I have used the following code for the creating xml from the C# class.
public string CreateXML(Order order)
{
XmlDocument xmlDoc = new XmlDocument();
XmlSerializer xmlSerializer = new XmlSerializer(typeof(Order));
// Creates a stream whose backing store is memory.
using (MemoryStream xmlStream = new MemoryStream())
{
xmlSerializer.Serialize(xmlStream, order);//,ns
xmlStream.Position = 0;
//Loads the XML document from the specified string.
xmlDoc.Load(xmlStream);
return xmlDoc.InnerXml;
}
}
I am not sure its a right approach for creating xml from C# classes. Please guide me to get the following xml output from c# class.
<?xml version="1.0"?>
<Order xmlns="http://example.com/xml/1.0" >
<Number Type="mobile">9999999999</Number>
<TrackStartDateTime>2015-05-30 11:00 ET</TrackStartDateTime>
<Notifications>
<Notification>
<PartnerMPID>99999999</PartnerMPID>
<IDNumber>L563645</IDNumber>
<TrackDurationInHours>120</TrackDurationInHours>
<TrackIntervalInMinutes>240</TrackIntervalInMinutes>
</Notification>
</Notifications>
<Carrier>
<Dispatcher>
<DispatcherName>?</DispatcherName>
<DispatcherPhone>0</DispatcherPhone>
<DispatcherEmail>?</DispatcherEmail>
</Dispatcher>
</Carrier>
</Order>
Here is a way to do it...
Just create a new XDocument and set the namespace that you want on it and transplant the original xml descendant into it, like so:
var xml = "<?xml version=\"1.0\"?><Order xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><Number Type=\"mobile\">9999999999</Number></Order>";
var xdoc = XDocument.Parse(xml);
var ns = XNamespace.Get("http://example.com/xml/1.0");
var xdoc2 = new XDocument(new XDeclaration("1.0", null, null),
new XElement(ns + "Order", xdoc.Root.Descendants()));
See here for working sample: https://dotnetfiddle.net/JYCL95
For this case it should be sufficient to simply add a null namespace to the XMLRoot decoration used on your class definition.
[XmlRoot("Order", Namespace = null)]
public class Order
{
[XmlElement("Number")]
public Number Number;
[XmlElement("TrackStartDateTime")]
public string TrackStartDateTime;
[XmlElement("Notifications")]
public Notifications Notifications;
[XmlElement("Carrier")]
public Carrier Carrier;
The serializer should do the rest.
I'm trying to parse this to XML using webservice:
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://www.xx.com/zz/Domain")]
Public class A
{
public int element1;
public int element2;
}
This gives
<A>
<element1 xlmns="http://www.xx.com/zz/Domain">1</element1>
<element2 xlmns="http://www.xx.com/zz/Domain">1</element1>
</A>
What should i use instead of XmlTypeAttribute to get
<A xlmns="http://www.xx.com/zz/Domain">
<element1>1</element1>
<element2>1</element1>
</A>
Use the XmlRoot attribute instead:
[XmlRoot( Namespace = "http://www.xx.com/zz/Domain")>
Public class A
{
public int element1;
public int element2;
}
EDIT: regarding your comment, could you give your serialization method? I think there may be something there since the following:
[XmlRoot(Namespace = "http://www.xx.com/zz/Domain")]
public class RootA
{
public int element1;
public int element2;
}
[XmlType(Namespace = "http://www.xx.com/zz/Domain")]
public class TypeA
{
public int element1;
public int element2;
}
internal class Program
{
private static void Main(string[] args)
{
Serialize<TypeA>();
Serialize<RootA>();
Console.ReadLine();
}
public static void Serialize<T>() where T : new()
{
Console.WriteLine();
Console.WriteLine();
var serializable = new T();
System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(serializable.GetType());
Console.WriteLine(serializable.GetType().Name);
x.Serialize(Console.Out, serializable);
Console.WriteLine();
Console.WriteLine();
}
}
outputs the expected result:
TypeA
<?xml version="1.0" encoding="ibm850"?>
<TypeA xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://w
ww.w3.org/2001/XMLSchema">
<element1 xmlns="http://www.xx.com/zz/Domain">0</element1>
<element2 xmlns="http://www.xx.com/zz/Domain">0</element2>
</TypeA>
RootA
<?xml version="1.0" encoding="ibm850"?>
<RootA xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://w
ww.w3.org/2001/XMLSchema" xmlns="http://www.xx.com/zz/Domain">
<element1>0</element1>
<element2>0</element2>
</RootA>
I have 2 classes as defined below:
[Serializable()]
public class Topology
{
[XmlElement("floors")]
public Floor[] Floors { get; set; }
}
[Serializable()]
public class Floor
{
[XmlElement("name")]
public string name { get; set; }
[XmlElement("map_path")]
public string map_path { get; set; }
}
I want to deserialize the xml file shown below and i use the below specified method to deserialize the xml file.
XMLFile:
<?xml version="1.0" encoding="iso-8859-9"?>
<Topology>
<floors>
<floor id="1">
<name>1</name>
<map_path>C:\</map_path>
</floor>
<floor id="2">
<name>2</name>
<map_path>D:\</map_path>
</floor>
</floors>
</Topology>
Deserialize Method:
static void Main(string[] args)
{
XmlSerializer serializer = new XmlSerializer(typeof(Topology));
StreamReader reader = new StreamReader(#"C:\topology2.xml");
Topology top = (Topology)serializer.Deserialize(reader);
reader.Close();
for (int i = 0; i < top.Floors.Length; i++ )
Console.WriteLine(top.Floors[i].name + top.Floors[i].map_path);
Console.ReadLine();
}
I can get "Floors" but i couldn't get the name and map_path node values. What should i do?
Your XML file is not properly formatet for the xml serializer to read. Please follow the following formating:
<?xml version="1.0" encoding="iso-8859-9"?>
<Topology>
<floors id="1">
<name>1</name>
<map_path>C:\</map_path>
</floors>
<floors id="2">
<name>1</name>
<map_path>C:\</map_path>
</floors>
</Topology>