How to add xsi:schemaLocation to serialized object - c#

How can I add the following xsi:schemaLocation to a serialized class?
<ern:NewReleaseMessage xmlns:ern="http://ddex.net/xml/2010/ern-main/32"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
LanguageAndScriptCode="en"
xsi:schemaLocation="http://ddex.net/xml/2010/ern-main/32 http://ddex.net/xml/2010/ern-main/32/ern-main.xsd"
MessageSchemaVersionId="2010/ern-main/32">
Here is what I have done so far:
public class NewReleaseMessage
{
[XmlAttribute]
public string LanguageAndScriptCode { get; set; }
[XmlAttribute("schemaLocation", Namespace = "http://ddex.net/xml/2010/ern-main/32")]
public string schemaLocation = "http://ddex.net/xml/2010/ern-main/32 http://ddex.net/xml/2010/ern-main/32/ern-main.xsd";
[XmlAttribute]
public string MessageSchemaVersionId { get; set; }
[XmlElement()]
public MessageHeader MessageHeader { get; set; }
}
When I deserialize the xml to the object in VS I get:
{"The method or operation is not implemented."
There is an error in XML document (5, 44) - This actually points to the line: xsi:schemaLocation="http://ddex.net/xml/2010/ern-main/32 http://ddex.net/xml/2010/ern-main/32/ern-main.xsd"

Soultion:
[XmlAttribute(AttributeName = "schemaLocation", Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
public string schemaLocation { get; set; }

Below is what worked for me:
Note : "XmlAttributeAttribute"
[XmlAttributeAttribute(AttributeName = "schemaLocation", Namespace = "http://ddex.net/xml/2010/ern-main/32")]
public string schemaLocation = "http://ddex.net/xml/2010/ern-main/32 http://ddex.net/xml/2010/ern-main/32/ern-main.xsd";

Related

Deserialize only specific Nodes from Xml to Object

I am trying to take specific Nodes from an Xml and write it into a class. I have this.
public class TradeMark
{
[XmlElement]
public string MarkVerbalElementText { get; set; }
[XmlElement]
public int MarkCurrentStatusCode { get; set; }
[XmlElement]
public string ExpiryDate { get; set; } = "";
}
static void Main(string[] args)
{
XmlSerializer serializer = new XmlSerializer(typeof(TradeMark));
using (TextReader reader = new StreamReader(pathToImportFile))
{
tradeMark = (TradeMark)serializer.Deserialize(reader);
}
}
In my Xml Data, there are more Node than just these 3. Now when i run the Code it says ...... was not expected. I guess bc. It tries to deserialize everything than only these 3 Infomartionen in Class TradeMark.
Can anyone help?
XML
<?xml version="1.0" encoding="UTF-8"?>
<Transaction xmlns="http://euipo.europa.eu/trademark/data" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://euipo.europa.eu/trademark/data http://euipo.europa.eu/schemas/trademark/EM-TM-TradeMark-V3-2.xsd">
<TransactionHeader>
<SenderDetails>
<RequestProducerDateTime>2018-08-18T15:33:35</RequestProducerDateTime>
</SenderDetails>
</TransactionHeader>
<TradeMarkTransactionBody>
<TransactionContentDetails>
<TransactionIdentifier>017690538</TransactionIdentifier>
<TransactionCode>EM-Trade Mark</TransactionCode>
<TransactionData>
<TradeMarkDetails>
<TradeMark operationCode="Insert">
<RegistrationOfficeCode>EM</RegistrationOfficeCode>
<ApplicationNumber>017690538</ApplicationNumber>
<ApplicationDate>2018-01-16</ApplicationDate>
<RegistrationDate>2018-06-14</RegistrationDate>
<ApplicationLanguageCode>en</ApplicationLanguageCode>
<SecondLanguageCode>es</SecondLanguageCode>
<ExpiryDate>2028-01-16</ExpiryDate>
<MarkCurrentStatusCode milestone="23" status="1">Registered</MarkCurrentStatusCode>
<MarkCurrentStatusDate>2018-06-15</MarkCurrentStatusDate>
<KindMark>Individual</KindMark>
<MarkFeature>Figurative</MarkFeature>
<TradeDistinctivenessIndicator>false</TradeDistinctivenessIndicator>
<WordMarkSpecification>
<MarkVerbalElementText>Tiens</MarkVerbalElementText>
</WordMarkSpecification>
Most likely this happens because your XML has a default namespace and Transaction is within this namespace.
You need to mark your class with XmlRootAttribute like so:
[XmlRootAttribute("TradeMark", Namespace="http://euipo.europa.eu/trademark/data",
IsNullable = false)]
public class TradeMark
XmlIgnore is what you're looking for.
MSDN Docs
See clarification in this answer, as the docs only state XmlIgnore will be ignored on serialize, but will also be ignored when deserializing.
From your example:
public class TradeMark
{
[XmlElement]
public string MarkVerbalElementText { get; set; }
[XmlElement]
public int MarkCurrentStatusCode { get; set; }
[XmlElement]
public string ExpiryDate { get; set; } = "";
[XmlIgnore]
public string IgnoreMe { get; set; } // This will be ignored
}

Tricks for deserialize this xml element

A legacy application transmits data as xml elements.
<frame>
<reply>
<id>value_id</id>
<resultCode>value</resultCode>
<readSampleIDs>
<returnValue>
<Sample>
<SampleID> value_SampleID </SampleID>
<SamplePC> value_SamplePC </SamplePC>
<antennaName> value_antennaName </antennaName>
<channel> value_channel </channel>
<power> value_power </power>
<polarization> value_polarization </polarization>
<inventoried> value_inventoried </inventoried>
</Sample>
…
<Sample>
…
</Sample>
</returnValue>
</readSampleIDs>
</reply>
Currently the information is extracted parsing the string word by word.
I think that xml element can be deserialized into an object directly with XmlSerializer but I have some doubts on how to do it.
The element frame contains only one reply. Do I really need two different classes ?
Inside returnValue there can be zero or more Sample. In my class what is the correct type, List<Sample> or Sample[] ? Is there a real difference between the two options during deserialization ?
Most fields inside Sample are optional. How do I model this ?
When an object is serialized with XmlSerializer information about xml version and additional attributes on root element are automatically added such as:
<?xml version="1.0" encoding="utf-8"?>
<PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.cpandl.com">
They are not present in my example code so I'm afraid deserialization can complain about it and possibly fail.
Thanks
Filippo
If your xml contains a namespace (like in your example) then you can use these classes:
[XmlRoot(ElementName = "Sample")]
public class Sample
{
[XmlElement(ElementName = "SampleID")]
public string SampleID { get; set; }
[XmlElement(ElementName = "SamplePC")]
public string SamplePC { get; set; }
[XmlElement(ElementName = "antennaName")]
public string AntennaName { get; set; }
[XmlElement(ElementName = "channel")]
public string Channel { get; set; }
[XmlElement(ElementName = "power")]
public string Power { get; set; }
[XmlElement(ElementName = "polarization")]
public string Polarization { get; set; }
[XmlElement(ElementName = "inventoried")]
public string Inventoried { get; set; }
}
[XmlRoot(ElementName = "readSampleIDs")]
public class ReadSampleIDs
{
[XmlArray(ElementName = "returnValue")]
[XmlArrayItem(ElementName = "Sample")]
public List<Sample> Sample { get; set; }
}
[XmlRoot(ElementName = "reply", Namespace = "http://www.cpandl.com")]
public class Reply
{
[XmlElement(ElementName = "id")]
public string Id { get; set; }
[XmlElement(ElementName = "resultCode")]
public string ResultCode { get; set; }
[XmlElement(ElementName = "readSampleIDs")]
public ReadSampleIDs ReadSampleIDs { get; set; }
}
If you are only interested in node reply and this is the only one. You can deserialize only this node:
XNamespace loNameSpace = "http://www.cpandl.com";
XDocument loDoc = XDocument.Parse(Properties.Settings.Default.TransmitsData);
var loReplyElement = loDoc.Element(loNameSpace.GetName("PurchaseOrder"))
.Element(loNameSpace.GetName("frame"))
.Element(loNameSpace.GetName("reply"));
using (var loReader = loReplyElement.CreateReader())
{
var loSerializer = new XmlSerializer(typeof(Reply));
var loReply = (Reply)loSerializer.Deserialize(loReader);
Console.WriteLine(loReply.Id);
}

XML Deserialization error: xxxxx was not expected

I know there are several posts out there with this topic, but I can't seem to figure out what is the problem here. I have serialized and deserialized xml several times, and never had this error.
The exception message is:
There is an error in XML document (1, 2).
With InnerException:
<InvoiceChangeRequest xmlns=''> was not expected.
XML file I want to deserialize:
<ns1:InvoiceChangeRequest xmlns:ns1="http://kmd.dk/fie/external_invoiceDistribution">
<CONTROL_FIELDS>
<STRUCTURID>0000000001</STRUCTURID>
<OPERA>GET</OPERA>
<WIID>000050371220</WIID>
</CONTROL_FIELDS>
<HEADER_IN>
<MANDT>751</MANDT>
<BELNR>1234567890</BELNR>
</HEADER_IN>
<ITEMS>
<ITEM_FIELDS_IN>
<BUZEI>001</BUZEI>
<BUKRS>0020</BUKRS>
</ITEM_FIELDS_IN>
</ITEMS>
</ns1:InvoiceChangeRequest>
Class I'm trying to deserialize to:
[XmlRoot(Namespace = "http://kmd.dk/fie/external_invoiceDistribution", IsNullable = false)]
public class InvoiceChangeRequest
{
[XmlElement("CONTROL_FIELDS")] public ControlFields Styrefelter;
[XmlElement("HEADER_IN")] public HeaderIn HeaderfelterInd;
[XmlElement("ITEMS")] public Items Linjer;
}
public class HeaderIn
{
[XmlElement("MANDT")] public string Kommunenummer;
[XmlElement("BELNR")] public string RegnskabsbilagsNummer;
}
public class Items
{
[XmlElement("ITEM_FIELDS_IN")] public Itemfield[] ItemfelterInd;
}
public class Itemfield
{
[XmlElement("BUZEI")] public string Linjenummer;
[XmlElement("BUKRS")] public string Firmakode;
}
Deserialization code:
XmlSerializer serializer = new XmlSerializer(typeof(InvoiceChangeRequest));
var request = serializer.Deserialize(new StringReader(output)) as InvoiceChangeRequest;
In your XML file your root element is the namespace http://kmd.dk/fie/external_invoiceDistribution with prefix ns1.
The element <CONTROL_FIELDS> isn't because it isn't prefixed. Your serialization class doesn't take this into account though. That means that it expects that <CONTROL_FIELDS> and the other elements are ALSO in the ns1 namespace.
To get the serializer parse the elements correctly add the Namespace to the elements, setting it to an empty string:
[XmlRoot(Namespace = "http://kmd.dk/fie/external_invoiceDistribution", IsNullable = false)]
public class InvoiceChangeRequest
{
[XmlElement("CONTROL_FIELDS", Namespace = "")]
public ControlFields Styrefelter { get; set; }
[XmlElement("HEADER_IN", Namespace = "")]
public HeaderIn HeaderfelterInd { get; set; }
[XmlElement("ITEMS", Namespace = "")]
public Items Linjer { get; set; }
}
This will de-serialize the given XML as intended.
In case of de-serialization issues I often create the classes in memory and then serialize that so I can inspect the resulting XML. That often gives clues on what is missing or being added compared to the input document:
var ms = new MemoryStream();
serializer.Serialize(ms, new InvoiceChangeRequest {
Styrefelter = new ControlFields { Opera="test"}
});
var s = Encoding.UTF8.GetString(ms.ToArray());
And then inspect s for differences.
You can replace 'ns1:' with string.Empty.
Below classes should serialize.
public class Item
{
[XmlElement("BUZEI")]
public string Buzei { get; set; }
[XmlElement("BUKRS")]
public string Bukrs { get; set; }
}
public class Header
{
[XmlElement("MANDT")]
public string Mandt { get; set; }
[XmlElement("BELNR")]
public string Belnr { get; set; }
}
public class ControlFields
{
[XmlElement("STRUCTURID")]
public string StructuredId { get; set; }
[XmlElement("OPERA")]
public string Opera { get; set; }
[XmlElement("WIID")]
public string Wild { get; set; }
}
public class InvoiceChangeRequest
{
[XmlElement("CONTROL_FIELDS")]
public ControlFields ControlFields { get; set; }
[XmlElement("HEADER_IN")]
public Header Header { get; set; }
[XmlArray("ITEMS")]
[XmlArrayItem("ITEM_FIELDS_IN")]
public List<Item> Items { get; set; }
}

De-Serialization of a nested object tree using WCF DataContractSerializer

I have the following SOAP XML Response
<startProcessResponseDDWEBCall xmlns="http://eclipse.org/stardust/models/generated/OmniLinkServices">
<ProcessInstanceOid>13430</ProcessInstanceOid>
<Return>
<DDWEBCallResponseData>
<DDWEBCallOutput xmlns="http://www.infinity.com/bpm/model/OmniLinkServices/DDWEBCallOutput">
<CommonResponse xmlns=""/>
<reportContent xmlns=""><![CDATA[<HTML><BODY><P>The OmniPlus Host Server process DDWEB had the following error: </P><P><TEXT="FF000">E23 TX00087 Textfile not found: TestScript # 000003\\\ </TEXT></P><P>processing terminated</P></BODY></HTML>]]></reportContent>
</DDWEBCallOutput>
</DDWEBCallResponseData>
</Return>
</startProcessResponseDDWEBCall>
This is the SOAP body of a WCF web service call response. I have the following object hierarchy to represent the response
[DataContract(Namespace="http://www.infinity.com/bpm/model/OmniLinkServices/DDWEBCallOutput")]
public class OmniLinkExecuteScriptOutput
{
public string CommonResponse { get; set; }
[DataMember(Name = "reportContent")]
public string ReportContent { get; set; }
}
[DataContract(Namespace = "http://eclipse.org/stardust/models/generated/OmniLinkServices")]
public class OmniLinkExecuteScriptResponseData
{
[DataMember(Name="DDWEBCallOutput")]
public OmniLinkExecuteScriptOutput Output { get; set; }
}
[DataContract(Namespace = "http://eclipse.org/stardust/models/generated/OmniLinkServices")]
public class OmniLinkExecuteScriptReturn
{
[DataMember(Name="DDWEBCallResponseData")]
public OmniLinkExecuteScriptResponseData ReponseData { get; set; }
}
[MessageContract(WrapperName = "startProcessResponseDDWEBCall", WrapperNamespace = "http://eclipse.org/stardust/models/generated/OmniLinkServices", IsWrapped = true)]
public class OmniLinkExecuteScriptResponse
{
[MessageBodyMember(Name = "ProcessInstanceOid", Namespace = "http://eclipse.org/stardust/models/generated/OmniLinkServices")]
public string ProcessInstanceOid { get; set; }
[MessageBodyMember(Name = "Return", Namespace = "http://eclipse.org/stardust/models/generated/OmniLinkServices")]
public OmniLinkExecuteScriptReturn Return { get; set; }
}
The object OmniLinkExecuteScriptResponse is the return type of a method call. Everything is deserialized fine except for the inner most object, the object representing the DDWEBCallOutput node. I don't see any errors in the WCF plumbing, and the value of the Output property on the OmniLinkExecuteScriptResponseData object is always null.
Can anybody tell what I'm doing wrong?
Your problem is that you are applying the [DataContract(Namespace = "...")] attributes at the wrong level in your class hierarchy. This attribute controls the namespace to which all data members of an instance of a type are serialized, and in addition controls the root element namespace if the instance is being serialized as such.
Thus you need to do the following:
// Its members are in the empty namespace
[DataContract(Namespace = "")]
public class OmniLinkExecuteScriptOutput
{
[DataMember]
public string CommonResponse { get; set; }
[DataMember(Name="reportContent")]
public string ReportContent { get; set; }
}
// Its members are in the DDWEBCallOutput namespace
[DataContract(Namespace = "http://www.infinity.com/bpm/model/OmniLinkServices/DDWEBCallOutput")]
public class OmniLinkExecuteScriptResponseData
{
[DataMember(Name = "DDWEBCallOutput")]
public OmniLinkExecuteScriptOutput Output { get; set; }
}
// Its members are in the OmniLinkServices namespace
[DataContract(Namespace = "http://eclipse.org/stardust/models/generated/OmniLinkServices")]
public class OmniLinkExecuteScriptReturn
{
[DataMember(Name = "DDWEBCallResponseData")]
public OmniLinkExecuteScriptResponseData ReponseData { get; set; }
}
OmniLinkExecuteScriptResponse can remain unchanged.

XML Deserialization with multiple namespaces

I'm trying to deserialize the following xml into an Object.
Xml got multiple namespaces.
I tried to deserialize the Xml into an object.
The object (data) has a reference to the LastChannel Object.
But when i ask for data.channel which should give me the LastChannel, i get a nullpointer.
Xml:
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://purl.org/rss/1.0/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:mp="http://www.tagesschau.de/rss/1.0/modules/metaplus/"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
<title>title</title>
<description>Default description</description>
<dc:date>2013-04-15 13:27:06</dc:date>
<sy:updateBase>2013-04-15 13:27:06</sy:updateBase>
<sy:updatePeriod>hourly</sy:updatePeriod>
<sy:updateFrequency>12</sy:updateFrequency>
</channel>
</rdf:RDF>
The objects look like this:
[XmlRoot("RDF", Namespace = "http://www.w3.org/1999/02/22-rdf-syntax-ns#")]
public class LastRss
{
[XmlElement("channel")]
public LastChannel channel { get; set; }
}
and
public class LastChannel
{
[XmlElement("title")]
public string title { get; set; }
[XmlElement("description")]
public string description { get; set; }
[XmlElement("date", Namespace = "http://purl.org/dc/elements/1.1/")]
public DateTime date { get; set; }
[XmlElement("updateBase", Namespace = "http://purl.org/rss/1.0/modules/syndication/")]
public DateTime updateBase { get; set; }
[XmlElement("updatePeriod", Namespace = "http://purl.org/rss/1.0/modules/syndication/")]
public string updatePeriod { get; set; }
[XmlElement("updateFrequency", Namespace = "http://purl.org/rss/1.0/modules/syndication/")]
public int updateFrequency { get; set; }
}
Anybody sees why the data.channel ist null?
Serializer:
LastRss data = new LastRss();
XmlSerializer serializer = new XmlSerializer(typeof(LastRss));
System.IO.TextReader reader = new System.IO.StringReader(xml);
try
{
object o = serializer.Deserialize(reader);
data = (LastRss)o;
}
Your channel is in the default xmlns, viz http://purl.org/rss/1.0/
[XmlElement("channel", Namespace = "http://purl.org/rss/1.0/")]
public LastChannel channel { get; set; }
You'll also need to correct the date formats e.g. 2013-04-15**T**13:27:06

Categories

Resources