Serializing XML with strange namespaces? - c#

Question: How does the class for the serialization of this XML content look ?
<?xml version="1.0" encoding="utf-8"?>
<vcc:CreateTextSearchResponse xmlns:vcc="urn:veloconnect:catalog-1.1" xmlns:vct="urn:veloconnect:transaction-1.0">
<vct:BuyersID>12345</vct:BuyersID>
<vct:ResponseCode>200</vct:ResponseCode>
<vct:TransactionID>225</vct:TransactionID>
<vct:StatusCode>2</vct:StatusCode>
<vct:IsTest>false</vct:IsTest>
<vcc:TotalCount>3876</vcc:TotalCount>
</vcc:CreateTextSearchResponse>
If I let it run through xsd.exe, it generates an error.
I have no problem generating this:
<?xml version="1.0" encoding="utf-8"?>
<CreateTextSearchResponse>
<BuyersID>15942</BuyersID>
<ResponseCode>200</ResponseCode>
<TransactionID>225</TransactionID>
<StatusCode>2</StatusCode>
<IsTest>false</IsTest>
<TotalCount>3876</TotalCount>
</CreateTextSearchResponse>
It's just that I need those namespaces to deserialize it (and later on reserialize), so I can't just leave it like this (it's needed by a 3rd party web-service)...

Like this:
[XmlRoot(Namespace = CreateTextSearchResponse.CatalogNamespace)]
public class CreateTextSearchResponse
{
public const string CatalogNamespace = "urn:veloconnect:catalog-1.1",
TransactionNamespace = "urn:veloconnect:transaction-1.0";
[XmlElement(Namespace=TransactionNamespace)]
public int BuyersId { get; set; }
[XmlElement(Namespace = TransactionNamespace)]
public int ResponseCode { get; set; }
[XmlElement(Namespace = TransactionNamespace)]
public int TransactionID { get; set; }
[XmlElement(Namespace = TransactionNamespace)]
public int StatusCode { get; set; }
[XmlElement(Namespace = TransactionNamespace)]
public bool IsTest { get; set; }
[XmlElement(Namespace = CatalogNamespace)]
public int TotalCount { get; set; }
}
public static void Main()
{
var ser = new XmlSerializer(typeof(CreateTextSearchResponse));
var obj = new CreateTextSearchResponse
{
BuyersId = 12345,
ResponseCode = 200,
TransactionID = 225,
StatusCode = 2,
IsTest = false,
TotalCount = 3876
};
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("vcc", CreateTextSearchResponse.CatalogNamespace);
ns.Add("vct", CreateTextSearchResponse.TransactionNamespace);
ser.Serialize(Console.Out, obj, ns);
}

unfortunately there are special characters in your namesapce that Xml can't handle

Related

How to force to show every class tag during XML serialisation in C#

I have the following console program
using System.Xml;
using System.Xml.Serialization;
namespace myTry {
public class CI_ResponsibleParty{
public CI_ResponsibleParty() { }
[XmlElement(Order = 0, ElementName = "individualName")]
public string IndividualName { get; set; }
[XmlElement(Order = 1, ElementName = "contactInfo")]
public CI_Contact ContactInfo { get; set; }
}
public class CI_Contact{
public CI_Contact() {}
[XmlElement(Order = 1, ElementName = "address")]
public CI_Address Address { get; set; }
}
public class CI_Address{
public CI_Address() {}
[XmlArray(ElementName = "deliveryPoint", Order = 0)]
[XmlArrayItem(typeof(string), ElementName = "CharacterString", Type = typeof(string))]
public List<string> DeliveryPoint { get; set; }
[XmlElement(Order = 1, ElementName = "city")]
public string City { get; set; }
[XmlAttribute(DataType = "ID", AttributeName = "id")]
public string Id { get; set; }
[XmlAttribute(AttributeName = "uuid")]
public string Uuid { get; set; }
}
}
namespace Application {
class Program {
public static void ReadXML() {
var b = new myTry.CI_ResponsibleParty() {
IndividualName = "dummy ind name",
ContactInfo = new myTry.CI_Contact {
Address = new myTry.CI_Address {
Id = "123",
Uuid = "123",
City = "dummuy city",
}
}
};
var writer = new System.Xml.Serialization.XmlSerializer(typeof(myTry.CI_ResponsibleParty));
var wfile = new System.IO.StreamWriter(#"CI_ResponsibleParty_write.xml");
writer.Serialize(wfile, b);
wfile.Close();
return;
}
static void Main(string[] args) {
ReadXML();
}
}
}
it produces
<?xml version="1.0" encoding="utf-8"?>
<CI_ResponsibleParty xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<individualName>dummy ind name</individualName>
<contactInfo>
<address id="123" uuid="123">
<city>dummuy city</city>
</address>
</contactInfo>
</CI_ResponsibleParty>
but I want to have CI_Contact and CI_Address tags as inner tags of contaxtInfo and address tags respectively. i.e.
<?xml version="1.0" encoding="utf-8"?>
<CI_ResponsibleParty xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<individualName>dummy ind name</individualName>
<contactInfo>
<CI_Contact>
<address id="123" uuid="123">
<CI_Address>
<city>dummuy city</city>
</CI_Address>
</address>
</CI_Contact>
</contactInfo>
</CI_ResponsibleParty>
How may I do so? What did I do wrong?

XML Deserialize to class

I am trying to deserialize an XDocument to a class. I am calling USPS the CityStateLookupResponse API. Every time I deserialize to my class object, the object is always null.
Here is my class
[Serializable()]
[XmlRoot("CityStateLookupResponse", IsNullable = false)]
public class CityStateLookUpResponse
{
[XmlAttribute("ID")]
public string Id { get; set; }
[XmlElement("City")]
public string City { get; set; }
[XmlElement("State")]
public string State { get; set; }
[XmlElement("Zip5")]
public string Zip { get; set; }
}
Below is the code I use to call USPS
XDocument requestDoc = new XDocument(
new XElement("CityStateLookupRequest",
new XAttribute("USERID", _postOfficeOptions.UserId),
new XElement("Revision", "1"),
new XElement("ZipCode",
new XAttribute("ID", "0"),
new XElement("Zip5", zipCode.ToString())
)
)
);
try
{
var url = _postOfficeOptions.Url + requestDoc;
var client = new WebClient();
var response = client.DownloadString(url);
var xdoc = XDocument.Parse(response.ToString());
XmlSerializer serializer = new XmlSerializer(typeof(CityStateLookUpResponse));
if (!xdoc.Descendants("ZipCode").Any()) return null;
return (CityStateLookUpResponse)serializer.Deserialize(xdoc.CreateReader());
}
catch (Exception ex)
{
throw new Exception("In CityStateLookUp:", ex);
}
This line of code always returns null
return (CityStateLookUpResponse)serializer.Deserialize(xdoc.CreateReader());
This is a valid response from the USPS API
<?xml version="1.0"?>
<CityStateLookupResponse><ZipCode ID="0"><Zip5>90210</Zip5>
<City>BEVERLY HILLS</City><State>CA</State></ZipCode>
</CityStateLookupResponse>
Any help would be appreciated
The problem is that you are trying to deserialize starting at the wrong node. The root node for your response is CityStateLookupResponse. That contains a list of ZipCode nodes, and it is the ZipCode nodes that correspond to your current CityStateLookUpResponse class.
You can fix this by changing your response class like this:
[Serializable()]
[XmlRoot("CityStateLookupResponse", IsNullable = false)]
public class CityStateLookupResponse
{
[XmlElement("ZipCode")]
public List<ZipCode> ZipCode { get; } = new();
}
[Serializable()]
[XmlRoot("ZipCode", IsNullable = false)]
public class ZipCode
{
[XmlAttribute("ID")]
public string Id { get; set; }
[XmlElement("City")]
public string City { get; set; }
[XmlElement("State")]
public string State { get; set; }
[XmlElement("Zip5")]
public string Zip { get; set; }
}

C# XmlSerializer define namespace with prefix in a child node

I need to create an XML document with C# that is like this:
<?xml version="1.0" encoding="utf-8"?>
<Container>
<Info>
<request xmlns:a="http://www.UKMail.com/Services/Contracts/DataContracts">
<a:AuthenticationToken>token</a:AuthenticationToken>
<a:Username>username</a:Username>
<a:ConsignmentNumber>12345</a:ConsignmentNumber>
</request>
</Info>
</Container>
The critical part is the namespace definition with a prefix (xmlns:a=...) is in a child node, not the root node. I have only been able to produce this document so far:
<?xml version="1.0" encoding="utf-8"?>
<Container xmlns:a="http://www.UKMail.com/Services/Contracts/DataContracts">
<Info>
<a:request>
<a:AuthenticationToken>token</a:AuthenticationToken>
<a:Username>username</a:Username>
<a:ConsignmentNumber>12345</a:ConsignmentNumber>
</a:request>
</Info>
</Container>
This is rejected by the web service - if you move the xmlns:a.. part to the request node the web service is happy with it.
This is how I am generating the XML at the moment:
class Program
{
static void Main(string[] args)
{
SerializeObject("XmlNamespaces.xml");
}
public static void SerializeObject(string filename)
{
var mySerializer = new XmlSerializer(typeof(Container));
// Writing a file requires a TextWriter.
TextWriter myWriter = new StreamWriter(filename);
// Creates an XmlSerializerNamespaces and adds two
// prefix-namespace pairs.
var myNamespaces = new XmlSerializerNamespaces();
myNamespaces.Add("a", "http://www.UKMail.com/Services/Contracts/DataContracts");
Container container = new Container
{
Info = new CancelConsignmentRequest
{
request = new CancelConsignmentRequestInfo
{
AuthenticationToken = "token",
ConsignmentNumber = "12345",
Username = "username"
}
}
};
mySerializer.Serialize(myWriter, container, myNamespaces);
myWriter.Close();
}
}
public class Container
{
public CancelConsignmentRequest Info { get; set; } = new CancelConsignmentRequest();
}
[XmlRoot(Namespace = "http://www.UKMail.com/Services/Contracts/ServiceContracts")]
public class CancelConsignmentRequest
{
[XmlElement(Namespace = "http://www.UKMail.com/Services/Contracts/DataContracts")]
public CancelConsignmentRequestInfo request { get; set; } = new CancelConsignmentRequestInfo();
}
public class CancelConsignmentRequestInfo
{
[XmlElement(Namespace = "http://www.UKMail.com/Services/Contracts/DataContracts", Order = 0)]
public string AuthenticationToken { get; set; }
[XmlElement(Namespace = "http://www.UKMail.com/Services/Contracts/DataContracts", Order = 1)]
public string Username { get; set; }
[XmlElement(Namespace = "http://www.UKMail.com/Services/Contracts/DataContracts", Order = 2)]
public string ConsignmentNumber { get; set; }
}
I have not been able to work out how to place the namespace definition with a prefix in one of the child nodes. Does anyone know how to do this in C# please? Thanks.
This is possible. The code below does what you are asking for.
class Program
{
static void Main(string[] args)
{
SerializeObject("XmlNamespaces.xml");
}
public static void SerializeObject(string filename)
{
var mySerializer = new XmlSerializer(typeof(Container));
// Writing a file requires a TextWriter.
TextWriter myWriter = new StreamWriter(filename);
// Creates an XmlSerializerNamespaces and adds two
// prefix-namespace pairs.
var myNamespaces = new XmlSerializerNamespaces();
//myNamespaces.Add("a", "http://www.UKMail.com/Services/Contracts/DataContracts");
Container container = new Container
{
Info = new CancelConsignmentRequest
{
request = new CancelConsignmentRequestInfo
{
AuthenticationToken = "token",
ConsignmentNumber = "12345",
Username = "username"
}
}
};
mySerializer.Serialize(myWriter, container, myNamespaces);
myWriter.Close();
}
}
public class Container
{
public CancelConsignmentRequest Info { get; set; } = new CancelConsignmentRequest();
}
public class CancelConsignmentRequest
{
public CancelConsignmentRequestInfo request { get; set; } = new CancelConsignmentRequestInfo();
}
[XmlRoot(Namespace = "http://www.UKMail.com/Services/Contracts/ServiceContracts")]
public class CancelConsignmentRequestInfo
{
[XmlNamespaceDeclarations]
public XmlSerializerNamespaces xmlns = new XmlSerializerNamespaces(
new[] { new XmlQualifiedName("a", "http://www.UKMail.com/Services/Contracts/DataContracts"), });
[XmlElement(Namespace = "http://www.UKMail.com/Services/Contracts/DataContracts", Order = 0)]
public string AuthenticationToken { get; set; }
[XmlElement(Namespace = "http://www.UKMail.com/Services/Contracts/DataContracts", Order = 1)]
public string Username { get; set; }
[XmlElement(Namespace = "http://www.UKMail.com/Services/Contracts/DataContracts", Order = 2)]
public string ConsignmentNumber { get; set; }
}

Serialize XmlAttribute which is an empty string [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I got a class which represents a soccerplayer:
public class PlayerExtended
{
[XmlAttribute("id")] public string Id { get; set; }
[XmlAttribute("shortName")] public string ShortName { get; set; }
[XmlAttribute("firstName")] public string FirstName { get; set; }
[XmlAttribute("surName")] public string SurName { get; set; }
[XmlAttribute("shirtNumber")] public string ShirtNumber { get; set; }
[XmlAttribute("actions")] public string Actions { get; set; }
[XmlAttribute("substitude")] public string Substitude { get; set; }
[XmlAttribute("grade")] public string Grade { get; set; }
[XmlAttribute("iconSmall")] public string IconSmall { get; set; }
[XmlAttribute("position")] public string Position { get; set; }
[XmlAttribute("squadPositionID")] public string SquadPositionId { get; set; }
[XmlAttribute("squadPosition")] public string SquadPosition { get; set; }
[XmlAttribute("inMinute")] public string InMinute { get; set; }
[XmlAttribute("outMinute")] public string OutMinute { get; set; }
[XmlAttribute("captain")] public string Captain { get; set; }
}
After assigning values to the properties one of the players looks like this:
The property "Actions" is an empty string (NOT NULL).
If I serialize it it looks like this:
<player id="51641" shortName="Bürki" firstName="Roman" surName="Bürki" shirtNumber="1" substitude="starter" grade="2,5" iconSmall="xxx.whatever.com" position="11" squadPositionID="1" squadPosition="Torwart"/>
But I want it to look like this:
<player id="51641" shortName="Bürki" firstName="Roman" surName="Bürki" shirtNumber="1" actions="" substitude="starter" grade="2,5" iconSmall="xxx.whatever.com" position="11" squadPositionID="1" squadPosition="Torwart"/>
So how do I serialize an XmlAttribute which is an empty string?
How are you generating your XML? I cannot seem to reproduce your issue.
public class Program
{
public static void Main(string[] args)
{
using var writer = new StringWriter();
var serializer = new XmlSerializer(typeof(Player));
serializer.Serialize(writer, new Player { Name = "", Age = 25 });
Console.WriteLine(writer);
}
}
public class Player
{
[XmlAttribute("name")]
public string Name { get; set; }
[XmlAttribute("age")]
public int Age { get; set; }
}
The code above results in the name attribute in the format you desire (name=""). Let me know if this answer is sufficient for you.
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml.Serialization;
// Runtime Target = .NET Core v2.1 or .NET Core v3.1
namespace XmlSerialize
{
class Program
{
static void Main(string[] args)
{
var mickey = new Employee { FirstName = "Mickey", LastName = "Mouse" };
var asterix = new Employee { FirstName = "Asterix", LastName = "" };
var obelix = new Employee { FirstName = "Obelix", LastName = null };
var nixnix = new Employee { FirstName = null, LastName = null };
Console.WriteLine(SerializeXml(mickey) + SerializeXml(asterix) + SerializeXml(obelix) + SerializeXml(nixnix));
}
public static string SerializeXml<T>(T instanceToSerialize)
{
var serializer = new XmlSerializer(instanceToSerialize.GetType(), string.Empty);
var result = string.Empty;
using (var stringWriter = new StringWriter())
{
serializer.Serialize(stringWriter, instanceToSerialize);
result = stringWriter.ToString();
}
return result;
}
}
[XmlRoot("Employee")]
public sealed class Employee
{
[XmlAttribute("FirstName")]
public string FirstName { get; set; }
[XmlIgnore]
public string LastName { get; set; }
[XmlAttribute("LastName")]
public string SerializableLastName // <------------ Might this help?
{
get { return this.LastName ?? string.Empty; }
set { this.LastName = value; }
}
[XmlElement]
public List<string> Skills { get; set; }
}
}
Output
<?xml version="1.0" encoding="utf-16"?>
<Employee FirstName="Mickey" LastName="Mouse" />
<Employee FirstName="Asterix" LastName="" />
<Employee FirstName="Obelix" LastName="" />
<Employee LastName="" />
setting the property value to string.Empty will do the trick. I am using XmlSerializer to convert the object to XML. If I set the property to string.Empty, this will result as empty attribute in XML. Here is the example
public class TestClass
{
[XmlAttribute("test1")]
public string test1 { get; set; }
[XmlAttribute("test2")]
public string test2 { get; set; }
}
var dd = new List<TestClass>();
dd.Add( new TestClass() { test1 = "asdf", test2 = string.Empty }); //will generate empty attribute for test2
dd.Add( new TestClass() { test1 = "asdf" }); //the attribute test2 will be ignored
using (var stringwriter = new System.IO.StringWriter())
{
var serializer = new XmlSerializer(dd.GetType());
serializer.Serialize(stringwriter, dd);
Console.WriteLine( stringwriter.ToString());
}
Output
<?xml version="1.0" encoding="utf-16"?>
<ArrayOfTestClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<TestClass test1="asdf" test2="" />
<TestClass test1="asdf" />
</ArrayOfTestClass>

deserialize a string (xml node like syntax) to c# object

I am trying to deserialize a string to object. Is xml node like syntax, but is not an xml (as there is no root node or namespace). This is what I have so far, having this error:
<delivery xmlns=''>. was not expected
Deserialize code:
var number = 2;
var amount = 3;
var xmlCommand = $"<delivery number=\"{number}\" amount=\"{amount}\" />";
XmlSerializer serializer = new XmlSerializer(typeof(Delivery));
var rdr = new StringReader(xmlCommand);
Delivery delivery = (Delivery)serializer.Deserialize(rdr);
Delivery object:
using System.Xml.Serialization;
namespace SOMWClient.Events
{
public class Delivery
{
[XmlAttribute(AttributeName = "number")]
public int Number { get; set; }
[XmlAttribute(AttributeName = "amount")]
public string Amount { get; set; }
public Delivery()
{
}
}
}
How can I avoid the xmlns error when deserializing ?
Change the Delivery class and add information about the root element (XmlRoot attribute):
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[XmlRoot("delivery")]
public class Delivery
{
[XmlAttribute(AttributeName = "number")]
public int Number { get; set; }
[XmlAttribute(AttributeName = "amount")]
public string Amount { get; set; }
public Delivery()
{ }
}
Add the root yourself like this:
XmlRootAttribute root = new XmlRootAttribute();
root.ElementName = "delivery";
// root.Namespace = "http://www.whatever.com";
root.IsNullable = true;
// your code goes below

Categories

Resources