I've tried several of the suggestions found on other SO answers for this same error but nothing has helped. Adding a namespace attr, using a blank namespace attr. Loading the string into an xmlDocument then rewriting it back to an xmlWriter. Using Serialazble instead of DataContract. Using xmlRoot attr with and without a namespace. Nothing works! Help.
I'm trying to instantiate a FillRequestExtended with the constructor that accepts an xml formatted string and always get the error Error in xml document (1, 2)
The Inner Exception reads: "http://schemas.datacontract.org/2004/07/WdRx.Exactus.Objects'> was not expected."
The class looks like so:
namespace WdRx.Exactus.Objects
{
[DataContract]
public class FillRequestExtended : IExtendedData
{
[DataMember]
[XmlElement]
public KeyValuePair<string, string>[] Properties { get; set; }
[DataMember]
[XmlElement]
public List<Payment> PaymentItems { get; set; }
public FillRequestExtended()
{
}
public FillRequestExtended(string xml)
{
FillRequestExtended extendedData;
XmlSerializer xs = new XmlSerializer(typeof(FillRequestExtended));
using (StringReader sr = new StringReader(xml))
{
XmlReader reader = XmlReader.Create(sr);
extendedData = (FillRequestExtended)xs.Deserialize(reader);
}
Properties = extendedData.Properties;
PaymentItems = new List<Payment>(extendedData.PaymentItems);
}
}
}
The string passed in is serialized elsewhere with no issue and looks like so:
<FillRequestExtended xmlns=\"http://schemas.datacontract.org/2004/07/WdRx.Exactus.Objects\"
xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">
<PaymentItems>
<Payment>
<Amount>-43.95</Amount>
<Summary>CCP PAYMENT - AUTH:014910</Summary>
</Payment>
<Payment>
<Amount>0.00</Amount>
<Summary>Type: VIS Account: ************5793 Expires: 05/16 Authorization: 014910</Summary>
</Payment>
</PaymentItems>
<Properties xmlns:a=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">
<a:KeyValuePairOfstringstring>
<a:key>RxDcDate</a:key>
<a:value>20150414</a:value>
</a:KeyValuePairOfstringstring>
<a:KeyValuePairOfstringstring>
<a:key>RefillStatus</a:key>
<a:value>PROFILED</a:value>
</a:KeyValuePairOfstringstring>
</Properties>
</FillRequestExtended>
There are at least two different XML deserializers. By decorating the class with [DataContract] you are forcing it to use the WCF serializer. In the deserialize code, you are using the normal XML object deserializer.
Related
I am retrieving XML documents from a web service I have no control over. The XML is formatted similarly to the following:
<?xml version="1.0"?>
<ns:obj xmlns:ns="somenamespace">
<address>1313 Mockingbird Lane</address>
<residents>5</residents>
</ns:obj>
where the root node is in the "ns" namespace, but none of its child elements are.
After some trial and error, I found that I could deserialize the document to a C# object by doing the following:
[XmlRoot(Namespace="somenamespace", ElementName="obj")]
public class xmlObject
{
[XmlElement(Namespace = "")]
public string address { get; set; }
[XmlElement(Namespace = "")]
public int residents { get; set; }
}
class Program
{
static void Main(string[] args)
{
string xml =
"<?xml version=\"1.0\"?>" +
"<ns:obj xmlns:ns=\"somenamespace\">" +
" <address>1313 Mockingbird Lane</address>" +
" <residents>5</residents>" +
"</ns:obj>";
var serializer = new XmlSerializer(typeof(xmlObject));
using (var reader = new StringReader(xml))
{
var result = serializer.Deserialize(reader) as xmlObject;
Console.WriteLine("{0} people live at {1}", result.residents, result.address);
// Output: "5 people live at 1313 Mockingbird lane"
}
}
}
If I omit the XmlElementAttribute on the individual members, I instead get an empty object. I.e. The output reads
0 people live at
(result.address is equal to null.)
I understand the rationale behind why the deserialization process works like this, but I'm wondering if there is a less verbose way to tell XmlSerializer that the child elements of the object are not in the same namespace as the root node.
The objects I'm working with in production have dozens of members and, for cleanliness sake, I'd like to avoid tagging all of them with [XmlElement(Namespace = "")] if it's easily avoidable.
You can combine XmlRootAttribute with XmlTypeAttribute to make it so the root element, and the root element's elements, have different namespaces:
[XmlRoot(Namespace="somenamespace", ElementName="obj")]
[XmlType(Namespace="")]
public class xmlObject
{
public string address { get; set; }
public int residents { get; set; }
}
Using the type above, if I deserialize and re-serialize your XML I get:
<q1:obj xmlns:q1="somenamespace">
<address>1313 Mockingbird Lane</address>
<residents>5</residents>
</q1:obj>
Sample fiddle.
If you know the contract with the web service, why not use a DataContractSerializer to deserialize the XML into the objects?
I have XML Serializable class with property Name
[Serializable]
public class Item
{
[XmlElement("name")]
public string Name { get; set; }
}
and I want it to be able to deserialize XML file that I have in two ways:
<item>
<name>Name</name>
</item>
and
<item>
<name value="Name" />
</item>
The first works fine but what should I do to be able to deserialize the second also with the same class?
XML Serialization attributes work both with serialization and deserialization. If we'll assume that it might be possible to use attributes for deserializing instance of Item from two different xml structures, then how serialization should work - should it serialize instance name to element value, or to attribute? Or to both? That's why you cannot deserialize two different xml structures into single class. Use two different classes or deserialize it manually without usage of XML Serialization attributes.
I found another way to solve my problem using only one class maybe someone will find this useful
[Serializable]
public class Item
{
[XmlElement("name")]
public NameElement NameElement { get; set; }
}
public class NameElement
{
[XmlAttribute("value")]
public string Value { get; set; }
[XmlText]
public string Text { get; set; }
[XmlIgnore]
public string Name
{
get { return String.IsNullOrEmpty(this.Value) ? this.Text : this.Value; }
set { this.Value = value; }
}
}
Maybe it's not super elegant but it works in both cases and uses the same class.
Since you have mentioned that XML data is coming from external sources, so obviously you don't have control over that.
Therefore you can follow any of the option as below:
Create separate class per XML data structure, because as far I know there is no way to control XML Deserialization when using XmlSerializer
You can use XDocument to read the XML by self, to overcome this limitation.
If going by second idea, I have created small Console Application to demonstrate that.
Main piece of code is as below:
MemoryStream xmlStream = new MemoryStream(Encoding.UTF8.GetBytes(xmlData));
XDocument doc = XDocument.Load(xmlStream);
var records = from record in doc.Descendants("item").Descendants()
select new Item(!record.IsEmpty ? record.Value : record.Attribute("value").Value);
Here I'm reading the element using LinqToXml and checking if the element is not empty, i.e. Value is not blank, then use Value otherwise read the value from element's Attribute.
Console application (Complete code):
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.Xml.Serialization;
namespace Console.TestApp
{
class Program
{
static string xmltypeFirst = #"<item>
<name>John</name>
</item>";
static string xmltypeSecond = #"<item>
<name value='Smith' />
</item>";
static void Main(string[] args)
{
var data = xmltypeFirst;
var result = Deserialize(data).ToList();
Console.WriteLine("Name: " + result[0].Name);
data = xmltypeSecond;
result = Deserialize(data).ToList();
Console.WriteLine("Name: " + result[0].Name);
Console.WriteLine("Press any to key to exit..");
Console.ReadLine();
}
private static IEnumerable<Item> Deserialize(string xmlData)
{
MemoryStream xmlStream = new MemoryStream(Encoding.UTF8.GetBytes(xmlData));
XDocument doc = XDocument.Load(xmlStream);
var records = from record in doc.Descendants("item").Descendants()
select new Item(!record.IsEmpty ? record.Value : record.Attribute("value").Value);
return records;
}
}
[Serializable]
public class Item
{
public Item(string name)
{
this.Name = name;
}
[XmlElement("name")]
public string Name { get; set; }
}
}
Note: To run this you will need to add reference to System.Xml.Linq.dll in your project.
Reference: here
I'm having problems deserializing an XML response that I receive from a web service. The response looks like this:
<CreateSubscribersResultCollection xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<CreatedSubscriberIds xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<a:long>206464306</a:long>
<a:long>306664316</a:long>
</CreatedSubscriberIds>
<FailedCreatedSubscribers xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays" />
</CreateSubscribersResultCollection>
The code I use to deserialize the XML looks like this:
internal T GetQueuedResults<T>(string url)
{
WebRequest request = GetRequestObject(url, "GET");
var httpResponse = (HttpWebResponse)request.GetResponse();
using (var responseStream = httpResponse.GetResponseStream())
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
var response = (T)xmlSerializer.Deserialize(responseStream);
return response;
}
}
When I deserialize (passing the type CreateSubscribersResultCollection) I get no errors at all, instead the CreatedSubscriberIds has the length of 0. I am pretty sure that the error lies in how I've designed the CreateSubscribersResultCollection class, but I can't figure out what the error might be. The class looks like this:
[DataContract]
public class CreateSubscribersResultCollection : RequestBase
{
[XmlArray("CreatedSubscriberIds")]
[XmlArrayItem(typeof(long))]
public List<long> CreatedSubscriberIds { get; set; }
[XmlElement("FailedCreatedSubscribers")]
public string FailedCreatedSubscribers { get; set; }
}
When I instantiate the class and serialize it, for debugging purposes, I get these results:
<CreateSubscribersResultCollection xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<CreatedSubscriberIds>
<long>206464306</long>
<long>306664316</long>
</CreatedSubscriberIds>
<FailedCreatedSubscribers />
</CreateSubscribersResultCollection>
I hope there's someone out there who knows what I'm doing wrong. I have been banging my head against this for too long now and Google has been no help to me.
Try specifying the namespace like that:
[DataContract]
public class CreateSubscribersResultCollection : RequestBase
{
[XmlArray("CreatedSubscriberIds")]
[XmlArrayItem(typeof(long), Namespace="http://schemas.microsoft.com/2003/10/Serialization/Arrays")]
public List<long> CreatedSubscriberIds { get; set; }
[XmlElement("FailedCreatedSubscribers")]
public string FailedCreatedSubscribers { get; set; }
}
Make sure you GetResponseStream() has a data in it. To test try saving this into a file instead of doing network connection. Save it to data file and deserialize. If it is being serialized, that is most of the battle. Deserializing shouldn't be problem if it was serialized properly.
I have an XML string like this:
<Summary>Foo</Summary><Description>Bar</Description>
I want to read this into a class object:
class Foobar()
{
string Summary {get;set;}
string Description {get;set;}
}
I tried using XmlTextReader, but it throws an exception that no root element was found. This is what I tried:
using (XmlTextReader reader = new XmlTextReader(new StringReader(comment)))
{
while (reader.Read())
//do something here
}
I also tried deserializing it directly into an object like this:
[XmlTypeAttribute]
public class Foobar
{
[XmlElementAttribute("Summary")]
public string Summary { get; set; }
[XmlElementAttribute("Description")]
public string Description { get; set; }
}
This fails as well because I cannot define a [XmlRootElement] for the class Foobar, since there is no root element.
Define a root element
<root>
<Summary>Foo</Summary>
<Description>Bar</Desciption>
</root>
You need to set root element for that your xaml would be
<root>
<Summary>Foo</Summary><Description>Bar</Description>
</root>
For Rootelement in XMLSeralizatoion : http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlrootattribute.aspx
The easiest way is probably to manually add a root element.
string xml = "<root>" + comment + "</root>";
Then you can parse it with whichever method you want.
Use a constructor form that allows for XMLFragments (chunks of XML that could be valid if put into a single element, but which are not so-rooted):
using (XmlTextReader reader = new XmlTextReader(comment, XmlNodeType.Element, null))
{
while (reader.Read())
//do something here
}
Better yet, use Create(), which gives more flexibility still.
I have a class Image implementing ISerializable:
[Serializable]
[XmlRoot(ElementName = "IMAGE")]
[TypeConverter(typeof(ImageTypeConverter))]
public class ImageResource : ISerializable {
[XmlAttribute(AttributeName = "TYPE")]
public string Extension{
get;
set;
}
}
I just want to know if we can get the xml node for an object of this class?
Suppose this object is serializes as
<IMAGE TYPE=".mpg"/>
I want to get this Node content as string.
The XML representation does not exist until you serialize the instance. Once you serialize it, you can manipulate it as XML.
Hint: you should be able to serialize directly into an XDocument:
XDocument doc = new XDocument();
using (XmlWriter writer = doc.CreateNavigator().AppendChild())
{
XmlSerializer ser = new XmlSerializer(typeof(ImageResource));
ser.Serialize(instance);
}
Never mind got the answer from below
link text