Hi I have 3 classes like that:
public abstract class XmlNs
{
public const string XmlnsAttribute = "urn:ebay:apis:eBLBaseComponents";
}
[Serializable]
public class BulkDataExchangeRequests : XmlNs
{
[XmlAttribute("xmlns")]
public string XmlNs = XmlnsAttribute;
[XmlElement("Header")]
public Header Header { get; set; }
[XmlElement("AddFixedPriceItemRequest")]
public List<AddFixedPriceItemRequest> ListAddFixedPriceItemRequest { get; set; }
}
[Serializable]
public class AddFixedPriceItemRequest : XmlNs
{
[XmlElement("ErrorLanguage")]
public string ErrorLanguage { get; set; }
[XmlElement("WarningLevel")]
public string WarningLevel { get; set; }
[XmlElement("Version")]
public string Version { get; set; }
[XmlElement("Item")]
public ItemType Item { get; set; }
[XmlAttribute("xmlns")]
public string XmlNs = XmlnsAttribute;
}
The problem is that when I serialize the object I get a correct xml but with no xmlns attribute in the AddFixedPriceItemRequest item, while in the BulkDataExchangeRequests the xmlns is correctly written....
Any help will be very appreciated...
You are nesting elements, and nested elements are in the same namespace as their parent elements, if you don't specify anything else. So in fact your serializer is correct to not output the xmlns attribute again, as it is not needed.
See:
<root xmlns="my-namespace">
<element>this is also in the namespace "my-namespace" without further declaration</element>
<so><are><child><elements></elements></child></are></so>
</root>
EDIT:
Even though eBay is obviously not conforming to standards here, there is a solution! You can declare namespaces for the .NET xml serializer in a very convenient manner, and these declarations are kept, even if they are repeated:
[Serializable]
public class BulkDataExchangeRequests : XmlNs
{
[XmlElement("Header")]
public Header Header { get; set; }
[XmlElement("AddFixedPriceItemRequest")]
public List<AddFixedPriceItemRequest> ListAddFixedPriceItemRequest { get; set; }
[XmlNamespaceDeclarations]
public XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces(new System.Xml.XmlQualifiedName[] { new System.Xml.XmlQualifiedName("", XmlnsAttribute) });
}
[Serializable]
public class AddFixedPriceItemRequest : XmlNs
{
[XmlElement("ErrorLanguage")]
public string ErrorLanguage { get; set; }
[XmlElement("WarningLevel")]
public string WarningLevel { get; set; }
[XmlElement("Version")]
public string Version { get; set; }
[XmlElement("Item")]
public ItemType Item { get; set; }
[XmlNamespaceDeclarations]
public XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces(new System.Xml.XmlQualifiedName[] { new System.Xml.XmlQualifiedName("", XmlnsAttribute) });
}
The output is as expected:
<?xml version="1.0" encoding="utf-16"?>
<BulkDataExchangeRequests xmlns:xsi="http://www.w3.org/2001/XMLSchema-Instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="urn:ebay:apis:eBLBaseComponents">
<AddFixedPriceItemRequest xmlns="urn:ebay:apis:eBLBaseComponents" />
<AddFixedPriceItemRequest xmlns="urn:ebay:apis:eBLBaseComponents" />
</BulkDataExchangeRequests>
Relevant documentation:
System.Xml.Serialization.XmlNamespaceDeclarations
System.Xml.Serialization.XmlSerializerNamespaces
Related
I have this class model here:
public class Config
{
public ConnectionConfig ConnectionConfig { get; set; }
[XmlAttribute(AttributeName="advanced")]
public bool AdvancedEnabled { get; set; }
}
public class ConnectionConfig
{
[XmlElement(ElementName = "instance")]
public List<InstanceConfig> Instances { get; set; }
}
public class InstanceConfig
{
[XmlText]
public string Uri { get; set; }
[XmlAttribute(AttributeName="username")]
public string Username { get; set; }
[XmlAttribute(AttributeName="password")]
public string Password { get; set; }
}
Serialized it is this XML:
<config advanced="false">
<ConnectionConfig>
<instance username="user1" password="123">http://localhost:1234</instance>
<instance username="user2" password="1234">http://localhost:1235</instance>
<instance username="user3" password="12345">http://localhost:1236</instance>
</ConnectionConfig>
</config>
But I want to have a XML like this:
<config advanced="false">
<instance username="user1" password="123">http://localhost:1234</instance>
<instance username="user2" password="1234">http://localhost:1235</instance>
<instance username="user3" password="12345">http://localhost:1236</instance>
</config>
So basically without "ConnectionConfig". But in my model I need "ConnectionConfig" as an own object.
What am I missing or not understanding?
I tried to move the [XmlElement(ElementName = "instance")] attribute to ConnectionConfig but still not my desired output.
I haven't verified it, but I think you might need to decorate the ConnectionConfig property to indicate that it is an element in its own right.
public class Config
{
[XmlElement("ConnectionConfig")]
public ConnectionConfig ConnectionConfig { get; set; }
[XmlAttribute(AttributeName="advanced")]
public bool AdvancedEnabled { get; set; }
}
I am having some difficulties figuring out how to correctly structure my classes to mirror the XML that I am attempting to deserialize. Most elements are coming through, but for example, in the XML below the UOMs object is not being deserialized.
Example XML:
<Items xmlns="http://www.manh.com/ILSNET/Interface" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Item>
<Desc>Desc Field Example Value</Desc>
<Item>PE0000009790</Item>
<ItemCategories>
<Action>SAVE</Action>
<Category1>COMPONENT</Category1>
<Category2>Category2ExampleValue</Category2>
</ItemCategories>
<ItemClass>
<Action>SAVE</Action>
<ItemClass>Example ItemClass</ItemClass>
</ItemClass>
<UOMS>
<UOM>
<Action>SAVE</Action>
<ConvQty>1</ConvQty>
<DimensionUm>IN</DimensionUm>
<Height>0.0</Height>
<Length>0.0</Length>
<QtyUm>EA</QtyUm>
<Sequence>1</Sequence>
<Weight>0</Weight>
<WeightUm>LB</WeightUm>
<Width>0.0</Width>
</UOM>
</UOMS>
</Item>
</Items>
I am using basic XML deserialization code, which works well but just providing for background:
using (FileStream fileStream = new FileStream(Filename, FileMode.Open))
{
this.CreatedObjects = (ItemList)serializer.Deserialize(fileStream);
}
The first class is below:
[XmlRoot(ElementName = "Items", Namespace = "http://www.manh.com/ILSNET/Interface")]
public class ItemList
{
[XmlElement("Item")]
public Item[] Items { get; set; }
}
public class Item
{
[XmlElement("ItemCategories")]
public ItemCategory[] Categories { get; set; }
[XmlElement("ItemClass")]
public ItemClass[] Classes { get; set; }
[XmlElement("UOMS")]
public ItemUOMS UOMs { get; set; }
[XmlElement("Desc")]
public string Description { get; set; }
[XmlElement("Item")]
public string Id { get; set; }
}
The second class, which I am struggling to populate, is below (this class is a member of the Item class shown above:
[XmlRoot(ElementName = "UOMS", Namespace = "http://www.manh.com/ILSNET/Interface")]
public class ItemUOMS
{
[XmlElement("UOM")]
public ItemUOM[] UOM { get; set; }
}
[XmlRoot(ElementName = "UOM", Namespace = "http://www.manh.com/ILSNET/Interface")]
public class ItemUOM
{
[XmlElement("Action")]
public string Action { get; }
[XmlElement("DimensionUm")]
public string DimensionUnit { get; }
[XmlElement]
public decimal Height { get; }
[XmlElement]
public decimal Length { get; }
[XmlElement("QtyUm")]
public string QtyUnit { get; }
[XmlElement("ConvQty")]
public decimal Quantity { get; }
[XmlElement]
public int Sequence { get; }
[XmlElement]
public decimal Weight { get; }
[XmlElement("WeightUm")]
public string WeightUnit { get; }
[XmlElement]
public decimal Width { get; }
}
Unfortunately, I don't get an error, but instead the UOMs objects are just default objects without any values being set. I tried to reference some XML to C# Class tools online that are supposed to output C# classes for you based on XML provided to the tool, but their classes didn't seem to solve the issue for me either. I attempted to use [XmlArray] / [XmlArrayItem], but neither had any effect either.
If you need any more information from me, please let me know. Thanks for any assistance/guidance you are able to provide in advance.
This is my first time to ask on stackoverflow and also the first time to work with xml files , so I don't think it can get worse than that.
I need to deserialize some long XML but the part thats bugging me is the following:
<CastleConfigSub xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../xsd/c5c.xsd" Format="1">
<ConfigFile Name="EdgeDetection">
<Interfaces>
<Interface Name="EdgeDetectionModule">
<Doc />
<Functions>
<Function Name="MonitorNoChanges">
<Doc>This Function checks that no edge has been detected at the specified digital channel for a specific time in msec
1. DigitalChanelToWatch: This is the digital Input channel to monitor edges on it.
2. TimeOut: This is the monitoring Period for the edges on the digitial input channel.
</Doc>
<Args>
<Arg xsi:type="ArgEnum" Name="DigitalChanelToWatch" Enum="DigitalInChannelID" />
<Arg xsi:type="ArgValue" Name="TimeOut" EncodedType="uint32" Unit="msec" />
</Args>
</Function>
</Functions>
</Interface>
</Interfaces>
</ConfigFile>
</CastleConfigSub>
public class CastleConfigSub
{
[XmlElement("Options")]
public Options options = new Options();
[XmlElement("ConfigFile")]
public ConfigFile configFile= new ConfigFile();
}
public class ConfigFile
{
[XmlElement("Doc")]
public string doc {get; set;}
[XmlElement("History")]
public History history = new History();
[XmlElement("Includes")]
public Includes includes = new Includes();
[XmlElement("Options")]
public Options options = new Options();
[XmlElement("DataTypes")]
public DataTypes dataTypes = new DataTypes();
[XmlArray("Interfaces")]
[XmlArrayItem("Interface")]
public List<Interface> interfaces = new List<Interface>();
}
public class Interface
{
[XmlAttribute("Name")]
public string name="";
[XmlElement("Doc")]
[XmlArray("Functions")]
[XmlArrayItem("Function")]
public List<Function> functions = new List<Function>();
}
public class Function
{
[XmlAttribute("Name")]
public string name="";
[XmlElement("Doc")]
public string doc="";
[XmlArray("Args")]
[XmlArrayItem("Arg")]
public List<Arg> args = new List<Arg>();
}
public class Arg
{
[XmlAttribute ("xsi:type")]
public string type = "";
[XmlAttribute("Name")]
public string name ="";
[XmlAttribute("EncodedType")]
public string encodedType="";
[XmlAttribute("Enum")]
public string enumName ="";
[XmlAttribute("Unit")]
public string unit="";
}
I know everthing is so messy but i couldnt do any better :/.
Please try this:
public class CastleConfigSub
{
public ConfigFile ConfigFile { get; set; }
[XmlAttribute()]
public byte Format { get; set; }
}
public class ConfigFile
{
public List<Interface> Interfaces { get; set; }
[XmlAttribute()]
public string Name { get; set; }
}
public class Interface
{
public object Doc { get; set; }
public List<Function> Functions { get; set; }
[XmlAttribute()]
public string Name { get; set; }
}
public class Function
{
public string Doc { get; set; }
[XmlArrayItem("Arg")]
public List<Arg> Args { get; set; }
[XmlAttribute()]
public string Name { get; set; }
}
[XmlInclude(typeof(ArgEnum))]
[XmlInclude(typeof(ArgValue))]
public class Arg
{
[XmlAttribute()]
public string Name { get; set; }
}
public class ArgEnum : Arg
{
[XmlAttribute()]
public string Enum { get; set; }
}
public class ArgValue : Arg
{
[XmlAttribute()]
public string EncodedType { get; set; }
[XmlAttribute()]
public string Unit { get; set; }
}
I do not know how many times Interface and Function elements exists. So I made the List collection.
The previous answer is a good one, and helped me to solve my issue, but I've got extra work to handle different namespaces in xml element and it's attribute value, so my solution is here:
Having following xml
<?xml version="1.0" encoding="utf-16"?>
<RootType xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://my.custom.namespace.com">
<description>some description</description>
<values>
<field>some field</field>
<value xsi:type="xsd:double">1000.00</value>
</values>
</RootType>
The deserialized objects set is following
[XmlRoot(ElementName = "RootType", Namespace = "http://my.custom.namespace.com")]
public sealed class Root
{
[XmlElement("description")]
public string Description { get; set; }
[XmlElement("values")]
public Value[] Values { get; set; }
}
public sealed class Value
{
[XmlElement("field")]
public string Field { get; set; }
[XmlElement("value", IsNullable = true)]
public ValueProperty ValueProperty { get; set; }
}
[XmlInclude(typeof(CustomDouble))]
[XmlRoot(Namespace = "http://my.custom.namespace.com")]
public class ValueProperty
{
[XmlText]
public string Value { get; set; }
}
[XmlType(TypeName = "double", Namespace = "http://www.w3.org/2001/XMLSchema")]
public class CustomDouble : ValueProperty
{
}
I have the following XML which I need to deserialize:
<?xml version="1.0" encoding="UTF-8" ?>
<event code="2wuj0ticofhzt" self="/events/2wuj0ticofhzt" revision="1260234836">
<name>Test Event 2013</name>
<partner-settings>
<partner-setting>
<registration-type code="1yfopbwhk" link="/registration-types/1yfopbwhk" />
<personnel code="3eclag1dsrjfi">
<free-badges>unlimited</free-badges>
</personnel>
<personnel code="0nxgc6mfec8yh">
<free-badges>3</free-badges>
</personnel>
</partner-setting>
<partner-setting>
<registration-type code="1ygg67prw" link="/registration-types/1ygg67prw" />
</partner-setting>
</partner-settings>
</event>
Here are my classes that I have created. (I only need to deserialize the fields I have in my classes.):
[XmlRoot("event")]
public class Event
{
[XmlAttribute("code")]
public string Code { get; set; }
[XmlAttribute("name")]
public string EventName { get; set; }
[XmlArray("partner-settings")]
public List<PartnerSetting> PartnerSettings { get; set; }
}
[XmlType("partner-setting")]
public class PartnerSetting
{
[XmlElement("registration-type")]
public RegistrationType RegistrationType { get; set; }
[XmlArray("personnel")]
public List<Personnel> Personnel { get; set; }
}
[XmlRoot("registration-type")]
public class RegistrationType
{
[XmlAttribute("code")]
public string Code { get; set; }
[XmlAttribute("name")]
public string RegistrationTypeName { get; set; }
[XmlElement("type")]
public string Type { get; set; }
}
[XmlType("personnel")]
public class Personnel
{
[XmlAttribute("code")]
public string Code { get; set; }
[XmlElement("free-badges")]
public int FreeBadges { get; set; }
}
When I currently deserialize the above XML it all works except from the Personnel object where I get 0 returned when I'm expecting to see 2.
I'm not doing anything differently when I'm trying to return a personnel list (i.e. XMLArray attribute, return a List) to a partner setting list but for some reason it won't deserialize.
You need to change the attribute into XmlElement to force each element in the list to be rendered as a single XML element:
[XmlElement("personnel")]
public List<Personnel> Personnel { get; set; }
i am having an XML string like
<?xml version="1.0"?>
<FullServiceAddressCorrectionDelivery xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<AuthenticationInfo xmlns="http://www.usps.com/postalone/services/UserAuthenticationSchema">
<UserId xmlns="">FAPushService</UserId>
<UserPassword xmlns="">Password4Now</UserPassword>
</AuthenticationInfo>
</FullServiceAddressCorrectionDelivery>
In Order to map the nodes with Class, i am having the class structure like
[Serializable]
public class FullServiceAddressCorrectionDelivery
{
[XmlElement("AuthenticationInfo")]
public AuthenticationInfo AuthenticationInfo
{
get;
set;
}
}
[Serializable]
public class AuthenticationInfo
{
[XmlElement("UserId")]
public string UserId
{
get;
set;
}
[XmlElement("UserPassword")]
public string UserPassword
{
get;
set;
}
}
For De-serialization , i used xmlserializer to De-serialize the object
byte[] byteArray = System.Text.Encoding.ASCII.GetBytes(xmlString);
MemoryStream stream = new MemoryStream(byteArray);
XmlSerializer xs = new XmlSerializer(typeof(FullServiceAddressCorrectionDelivery));
var result = (FullServiceAddressCorrectionDelivery)xs.Deserialize(stream);
but the value FullServiceAddressCorrectionDelivery object is always null..
please help me what i am doing wrong here....
Add namesapce on the XmlElement attribute as described here
[Serializable]
public class FullServiceAddressCorrectionDelivery
{
[XmlElement("AuthenticationInfo",
Namespace =
"http://www.usps.com/postalone/services/UserAuthenticationSchema")]
public AuthenticationInfo AuthenticationInfo
{
get;
set;
}
}
[Serializable]
public class AuthenticationInfo
{
[XmlElement("UserId", Namespace="")]
public string UserId
{
get;
set;
}
[XmlElement("UserPassword", Namespace = "")]
public string UserPassword
{
get;
set;
}
}