XSD Serialization to complex object

0

I am working with an XML document supplied by a vendor that I used XSD to convert to a serializable object.

Here is the template xml they provide.

<?xml version="1.0" encoding="UTF-8"?>
<doi_batch xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.crossref.org/schema/4.4.2 https://www.crossref.org/schemas/crossref4.4.2.xsd"
 xmlns="http://www.crossref.org/schema/4.4.2" xmlns:jats="http://www.ncbi.nlm.nih.gov/JATS1"
 xmlns:fr="http://www.crossref.org/fundref.xsd" version="4.4.2">
    <head>
        <doi_batch_id>arg_123_954</doi_batch_id>
        <timestamp>20190430133609</timestamp>
        <depositor>
            <depositor_name>Crossref</depositor_name>
            <email_address>pfeeney@crossref.org</email_address>
        </depositor>
        <registrant>Society of Metadata Idealists</registrant>
    </head>
    <body>
        <journal>
            <journal_metadata language="en">
                <full_title>Journal of Metadata Perfection</full_title>
                <abbrev_title>JOMPer</abbrev_title>
                <doi_data>
                    <doi>10.32013/487529</doi>
                    <resource>https://www.crossref.org/jomper</resource>
                </doi_data>
            </journal_metadata>
        </journal>
    </body>
</doi_batch>

The class is massive that it generates. With multiple classes that are used to assemble the above XML schema.

here is a pastebin of the class XSD generates;

https://pastebin.com/hjG5cCLW

Here is a picture of the class object from the explorer.

XMl Object Serialization

I created the create method with the intent of passing all needed properties to it and returning a copy of the object.

// Excerpt
public class CreateXml
    {
        public DoiBatch Create(JournalPostData jPost)
        {
            // Create Batch
            DoiBatch doiBatch = new DoiBatch();

            #region Header

            // Create header for batch
            DoiBatchHead doiHead = new DoiBatchHead();
            // create depositor
            DoiBatchHeadDepositor doiDepositor = new DoiBatchHeadDepositor
            {
                DepositorName = jPost.DepositorName,
                EmailAddress = jPost.DepositorEmail
            };
            // add depositor to head.
            doiHead.Depositor = new[] {doiDepositor};
            // give it a unique guid.
            doiHead.DoiBatchId = new Guid().ToString();
            // give it a timestamp. Don't use local culture so the date settings on system do not matter.
            doiHead.Timestamp = DateTime.Now.ToOADate().ToString(CultureInfo.InvariantCulture);
            // set owner organization.
            doiHead.Registrant = jPost.DepositorName;

            #endregion

            #region Body

            // create body
            DoiBatchBodyJournalJournalMetadata doiBody = new DoiBatchBodyJournalJournalMetadata();
            DoiBatchBodyJournalJournalMetadataDoiData doiBodyData = new DoiBatchBodyJournalJournalMetadataDoiData();
            // set DOI Reference ID and journal location.
            doiBodyData.Doi = jPost.DoiPrefix + jPost.RefNum;
            doiBodyData.Resource = jPost.BaseUrl + @"?refnum=" + jPost.RefNum;

            // Fill body

            doiBody.DoiData = new[] { doiBodyData };
            doiBody.FullTitle = jPost.Title;
            doiBody.AbbrevTitle = jPost.Title.Substring(0, 10); //truncate title.
            doiBody.Language = "EN";

            // Fill batch

            doiBatch.Head = new [] { doiHead };
            doiBatch.Body = new[] { new[]{ new []{doiBody}}};

            return doiBatch;
        #endregion
        }
    }

The issue comes when I instantiate the body section. It is expecting three nested arrays. I am not certain I did this correctly.

I serialize the object with this code;

XmlSerializer doiSubmit = new XmlSerializer(typeof (DoiBatch));

I get;

System.InvalidOperationException
  HResult=0x80131509
  Message=Unable to generate a temporary class (result=1).
error CS0030: Cannot convert type 'NORMIN.DOI.DoiBatchBodyJournalJournalMetadata[][]' to 'NORMIN.DOI.DoiBatchBodyJournalJournalMetadata[]'
error CS0029: Cannot implicitly convert type 'NORMIN.DOI.DoiBatchBodyJournalJournalMetadata[]' to 'NORMIN.DOI.DoiBatchBodyJournalJournalMetadata[][]'

  Source=NORMIN
  StackTrace:
   at NORMIN.JournalSubmit.btnSubmit_Click(Object sender, EventArgs e) in C:\Projects\normin\NORMIN\JournalSubmit.aspx.cs:line 65

  This exception was originally thrown at this call stack:
    [External Code]
    NORMIN.JournalSubmit.btnSubmit_Click(object, System.EventArgs) in JournalSubmit.aspx.cs
    [External Code]

I believe that this is due to the

doiBatch.Body = new[] { new[]{ new []{doiBody}}};

in the create method.

I have completely lost myself, any help figuring this out will be much appreciated.

xml
xsd
xml-serialization
asked on Stack Overflow Mar 9, 2021 by Richard Barnes • edited Mar 9, 2021 by Richard Barnes

1 Answer

0

In the provided example xml is a reference to the actual xsd used by your customer. I suggest to use that file to generate the class file and not derive it from the example xml.

generating a class from the xml is based on assumptions while the xsd is a proper data contract. You will see that a lot of the array's or list definitions will disappear then.

answered on Stack Overflow Mar 22, 2021 by martijn

User contributions licensed under CC BY-SA 3.0