Maurice Klimek
Maurice Klimek

Reputation: 1092

InvalidOperationException when deserializing custom XML (lack of namespace)

I have an XML document that starts with the following root:

<?xml version="1.0" encoding="UTF-8"?>
<JPK
    xmlns="http://jpk.mf.gov.pl/wzor/2019/09/27/09271/"
    xmlns:etd="http://crd.gov.pl/xml/schematy/dziedzinowe/mf/2018/08/24/eD/DefinicjeTypy/">
    <Naglowek>
        <KodFormularza kodSystemowy="SomeCode" wersjaSchemy="1-0">SomeCode</KodFormularza>
        <WariantFormularza>3</WariantFormularza>
        <CelZlozenia>1</CelZlozenia>
        <DataWytworzeniaJPK>2021-06-30T15:57:53</DataWytworzeniaJPK>
        <DataOd>2021-05-01</DataOd>
        <DataDo>2021-05-31</DataDo>
        <KodUrzedu>0000</KodUrzedu>
    </Naglowek>
    <Podmiot1>
        <IdentyfikatorPodmiotu>
            <etd:NIP>111111</etd:NIP>
            <etd:PelnaNazwa>SomeName</etd:PelnaNazwa>
        </IdentyfikatorPodmiotu>
        <AdresPodmiotu>
            <etd:Wojewodztwo>voivodeship</etd:Wojewodztwo>
            <etd:KodKraju>PL</etd:KodKraju>
            <etd:Powiat>Danzig</etd:Powiat>
            <etd:Gmina>Danzig</etd:Gmina>
            <etd:Ulica>SomeStreet</etd:Ulica>
            <etd:NrDomu>81</etd:NrDomu>
            <etd:NrLokalu>1</etd:NrLokalu>
            <etd:Miejscowosc>Danzig</etd:Miejscowosc>
            <etd:KodPocztowy>10-101</etd:KodPocztowy>
        </AdresPodmiotu>
    </Podmiot1>
    <!-- These can be many in the same element, there's no root for this list -->
    <Faktura>
        <KodWaluty>PLN</KodWaluty>
        <P_1>2021-05-04</P_1>
        <P_2A>11 / 1111</P_2A>
        <P_3A>Some Company</P_3A>
        <P_3B>Some Address</P_3B>
        <P_3C>Some Name</P_3C>
        <P_3D>Some Other Address</P_3D>
        <P_4B>Phone1</P_4B>
        <P_5B>Phone2</P_5B>
        <P_13_1>1.00</P_13_1>
        <P_14_1>1.25</P_14_1>
        <P_15>SomeDecimalNumber</P_15>
        <P_16>false</P_16>
        <P_17>false</P_17>
        <P_18>false</P_18>
        <P_18A>false</P_18A>
        <P_19>false</P_19>
        <P_20>false</P_20>
        <P_21>false</P_21>
        <P_22>false</P_22>
        <P_23>false</P_23>
        <P_106E_2>false</P_106E_2>
        <P_106E_3>false</P_106E_3>
        <RodzajFaktury>InvoiceType</RodzajFaktury>
    </Faktura>
    <!-- These can be many in the same element, there's no root for this list -->
    <FakturaCtrl>
        <LiczbaFaktur>1</LiczbaFaktur>
        <WartoscFaktur>2.00</WartoscFaktur>
    </FakturaCtrl>
    <!-- These can be many in the same element, there's no root for this list -->
    <FakturaWiersz>
        <P_2B>04/123</P_2B>
        <P_7>Text</P_7>
        <P_8B>1.000000</P_8B>
        <P_9A>7.00</P_9A>
        <P_11>7.00</P_11>
        <P_12>11</P_12>
    </FakturaWiersz>
    <FakturaWierszCtrl>
        <LiczbaWierszyFaktur>11</LiczbaWierszyFaktur>
        <WartoscWierszyFaktur>11.2</WartoscWierszyFaktur>
    </FakturaWierszCtrl>
</JPK>

It has capital letters. I have no influence on its definition, I need to adjust myself.

I've written a class for it:

    [XmlRoot(ElementName = "JPK", Namespace = "http://jpk.mf.gov.pl/wzor/2019/09/27/09271/", IsNullable = false)]
    public class Jpk
    {
        public Jpk() { }

        [XmlElement(ElementName = "Naglowek")]
        public JpkHeader Header { get; set; }

        [XmlElement(ElementName = "Podmiot1")]
        public JpkSubject Subject { get; set; }

        [XmlElement(ElementName = "Faktura")]
        public JpkInvoice[] Invoices { get; set; }

        [XmlElement(ElementName = "FakturaCtrl")]
        public JpkInvoiceControl[] InvoiceControls { get; set; }

        [XmlElement(ElementName = "FakturaWiersz")]
        public JpkInvoiceRow[] InvoiceRows { get; set; }

        [XmlElement(ElementName = "FakturaWierszCtrl")]
        public JpkInvoiceRowControl InvoiceRowControl { get; set; }
    }

    public class JpkHeader
    {
        [XmlElement(ElementName = "KodFormularza")]
        public string FormCode { get; set; }

        [XmlElement(ElementName = "WariantFormularza")]
        public string Variant { get; set; }

        [XmlElement(ElementName = "CelZlozenia")]
        public int Purpose { get; set; }

        [XmlElement(ElementName = "DataWytworzeniaJPK")]
        public DateTime CreationDate { get; set; }

        [XmlElement(ElementName = "DataOd")]
        public DateTime DateFrom { get; set; }

        [XmlElement(ElementName = "DataDo")]
        public DateTime DateTo { get; set; }

        [XmlElement(ElementName = "KodUrzedu")]
        public string OfficeCode { get; set; }
    }

    public class JpkInvoice
    {
        [XmlElement(ElementName = "KodWaluty")]
        public string CurrencyCode { get; set; }

        public DateTime P_1 { get; set; }
        public string P_2A { get; set; }
        public string P_3A { get; set; }
        public string P_3B { get; set; }
        public string P_3C { get; set; }
        public string P_3D { get; set; }
        public string P_4B { get; set; }
        public string P_5B { get; set; }
        public decimal P_13_1 { get; set; }
        public decimal P_14_1 { get; set; }
        public decimal P_15 { get; set; }
        public bool P_16 { get; set; }
        public bool P_17 { get; set; }
        public bool P_18 { get; set; }
        public bool P_18A { get; set; }
        public bool P_19 { get; set; }
        public bool P_20 { get; set; }
        public bool P_21 { get; set; }
        public bool P_22 { get; set; }
        public bool P_23 { get; set; }
        public bool P_106E_2 { get; set; }
        public bool P_106E_3 { get; set; }

        [XmlElement(ElementName = "RodzajFaktury")]
        public string InvoiceType { get; set; }
    }

    public class JpkInvoiceControl
    {
        [XmlElement(ElementName = "LiczbaFaktur")]
        public int InvoiceAmount { get; set; }

        [XmlElement(ElementName = "WartoscFaktur")]
        public decimal InvoiceValue { get; set; }
    }

    public class JpkInvoiceRow
    {
        public string P_2B { get; set; }
        public string P_7 { get; set; }
        public double P_8B { get; set; }
        public decimal P_9A { get; set; }
        public decimal P_11 { get; set; }
        public int P_12 { get; set; }

    }

    public class JpkInvoiceRowControl
    {
        [XmlElement(ElementName = "LiczbaWierszyFaktur")]
        public int InvoiceRowAmount { get; set; }

        [XmlElement(ElementName = "WartoscWierszyFaktur")]
        public decimal InvoiceRowSum { get; set; }
    }

    public class JpkSubject
    {
        [XmlElement(ElementName = "IdentyfikatorPodmiotu")]
        public SubjectID SubjectId { get; set; }

        [XmlElement(ElementName = "AdresPodmiotu")]
        public SubjectAddress Address { get; set; }
    }

    public class SubjectID
    {
        [XmlElement(ElementName = "etd:NIP")]
        public string NIP { get; set; }

        [XmlElement(ElementName = "etd:PelnaNazwa")]
        public string FullName { get; set; }
    }

    public class SubjectAddress
    {
        [XmlElement(ElementName = "etd:KodKraju")]
        public string CountryCode { get; set; }

        [XmlElement(ElementName = "etd:Wojewodztwo")]
        public string Province { get; set; }

        [XmlElement(ElementName = "etd:Powiat")]
        public string District { get; set; }

        [XmlElement(ElementName = "etd:Gmina")]
        public string Community { get; set; }

        [XmlElement(ElementName = "etd:Ulica")]
        public string StreetName { get; set; }

        [XmlElement(ElementName = "etd:NrDomu")]
        public int HouseNumber { get; set; }

        [XmlElement(ElementName = "etd:NrLokalu")]
        public int FlatNumber { get; set; }

        [XmlElement(ElementName = "etd:Miejscowosc")]
        public string City { get; set; }

        [XmlElement(ElementName = "etd:KodPocztowy")]
        public string PostalCode { get; set; }
    }

And I have my code that deserializes it:

var serializer = new XmlSerializer(typeof(Etc), new XmlRootAttribute("JPK"));
var streamReader = new StreamReader(@"C:\_NotInGit\sample.xml");
var smth = (Jpk)serializer.Deserialize(streamReader);

When I run this code I get

System.InvalidOperationException: 'There is an error in XML document (2, 2).' InvalidOperationException: was not expected.

at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
at System.Xml.Serialization.XmlSerializer.Deserialize(TextReader textReader)
at MyProject.Program.Main(String[] args) in C:\MyProject\Program.cs:line 15

I run my queries through the Internet:

My spider-sense tells me it might have to do with the second definition, but I'm not sure how to approach it. I tried to remove it (for science purposes), but it did not change the response.

Is there anything else I am missing?

Spoiler alert: It was (also) about the second namespace definition. Thankfully the accepted answer showed me how to declare it, and what to do with the etd part. That, and the removal of new XmlRootAttribute("JPK") from code.

Upvotes: 0

Views: 1160

Answers (1)

It all makes cents
It all makes cents

Reputation: 4983

When attempting to debug a XML deserialization issue, I find it helpful to serialize the class that I've created using some sample data. Then, I check if the data that I serialized (saved to a XML file) is the same as the XML file that I'm trying to deserialize.

In the XML data you posted, within Faktura, is the following:

   <P_15>SomeDecimalNumber</P_15>

Then in class JpkInvoice is the following:

   public decimal P_15 { get; set; }

This is an issue because the value in the XML file is a string, whereas the property is declared as decimal. Either the property data type needs to be string or the value in the XML file needs to be changed to a valid decimal value. For testing, in the XML, I replaced <P_15>SomeDecimalNumber</P_15> with <P_15>0</P_15>.

I've tested the following code with the XML that you provided - with the XML data modification described above. I changed the property names to match what's in the XML file as I find it easier that way. You can rename them if you like. Also, I prefer to use List instead of an array, so you'll notice that in the code as well.

In the code below, the following using statements are necessary:

using System.Collections.Generic;
using System.Xml;
using System.Xml.Serialization;

Create a class (name: Jpk)

Class: Jpk

[XmlRoot(ElementName = "JPK", Namespace = "http://jpk.mf.gov.pl/wzor/2019/09/27/09271/", IsNullable = false)]
public class Jpk
{
    [XmlElement(ElementName = "Naglowek")]
    public JpkNaglowek Naglowek { get; set; } = new JpkNaglowek(); //Header

    [XmlElement(ElementName = "Podmiot1")]
    public JpkPodmiot1 Podmiot1 { get; set; } = new JpkPodmiot1(); //Subject

    [XmlElement(ElementName = "Faktura")]
    public List<JpkFaktura> Faktura { get; set; } = new List<JpkFaktura>(); //Invoices

    [XmlElement(ElementName = "FakturaCtrl")]
    public List<JpkFakturaCtrl> FakturaCtrl { get; set; } = new List<JpkFakturaCtrl>(); //InvoiceControls

    [XmlElement(ElementName = "FakturaWiersz")]
    public List<JpkFakturaWiersz> FakturaWiersz { get; set; } = new List<JpkFakturaWiersz>(); //InvoiceRows

    [XmlElement(ElementName = "FakturaWierszCtrl")]
    public List<JpkFakturaWierszCtrl> FakturaWierszCtrl { get; set; } = new List<JpkFakturaWierszCtrl>(); //InvoiceRowControl

}

Class: JpkFaktura

public class JpkFaktura
{
    private string p_1 = string.Empty;

    [XmlIgnore]
    public DateTime P_1Dt { get; private set; } = DateTime.MinValue; //value of P_1 as DateTime

    [XmlElement]
    public string KodWaluty { get; set; }

    [XmlElement]
    public string P_1 
    {
        get
        {
            return this.p_1;
        }
        set
        {
            this.p_1 = value;
            
            //try to convert to DateTime
            DateTime dt = DateTime.MinValue;
            DateTime.TryParseExact(value, "yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out dt);

            //set value
            this.P_1Dt = dt;
        }
    }

    [XmlElement]
    public string P_2A { get; set; }

    [XmlElement]
    public string P_3A { get; set; }

    [XmlElement]
    public string P_3B { get; set; }

    [XmlElement]
    public string P_3C { get; set; }

    [XmlElement]
    public string P_3D { get; set; }

    [XmlElement]
    public string P_4B { get; set; }

    [XmlElement]
    public string P_5B { get; set; }

    [XmlElement]
    public decimal P_13_1 { get; set; }

    [XmlElement]
    public decimal P_14_1 { get; set; }

    [XmlElement]
    public decimal P_15 { get; set; }

    [XmlElement]
    public bool P_16 { get; set; } = false;

    [XmlElement]
    public bool P_17 { get; set; } = false;

    [XmlElement]
    public bool P_18 { get; set; } = false;

    [XmlElement]
    public bool P_18A { get; set; } = false;

    [XmlElement]
    public bool P_19 { get; set; } = false;

    [XmlElement]
    public bool P_20 { get; set; } = false;

    [XmlElement]
    public bool P_21 { get; set; } = false;

    [XmlElement]
    public bool P_22 { get; set; } = false;

    [XmlElement]
    public bool P_23 { get; set; } = false;

    [XmlElement]
    public bool P_106E_2 { get; set; } = false;

    [XmlElement]
    public bool P_106E_3 { get; set; } = false;

    [XmlElement]
    public string RodzajFaktury { get; set; }
}

Note: In the code above you'll notice a property named P_1Dt. It's a public property that holds the value of P_1 as DateTime. By specifying [XmlIgnore] this property will be ignored during deserialization/serialization. In the XML, the format of the data is yyyy-MM-dd (ex: 2021-05-01), which is why it's necessary to specify the data type as a string. If the data type is specified as DateTime, when serialized the data in the XML file would look like yyyy-MM-ddTHH:mm:ss (ex: 2021-05-01T00:00:00)

Class: JpkFakturaCtrl

public class JpkFakturaCtrl
{
    [XmlElement]
    public decimal LiczbaFaktur { get; set; }

    [XmlElement]
    public decimal WartoscFaktur { get; set; }
}

Class: JpkFakturaWiersz

public class JpkFakturaWiersz
{
    [XmlElement]
    public string P_2B { get; set; }

    [XmlElement]
    public string P_7 { get; set; }

    [XmlElement]
    public decimal P_8B { get; set; }

    [XmlElement]
    public decimal P_9A { get; set; }

    [XmlElement]
    public decimal P_11 { get; set; }

    [XmlElement]
    public int P_12 { get; set; }
}

Class: JpkFakturaWierszCtrl

public class JpkFakturaWierszCtrl
{
    [XmlElement]
    public decimal LiczbaWierszyFaktur { get; set; }

    [XmlElement]
    public decimal WartoscWierszyFaktur { get; set; }
}

Class: JpkNaglowek

public class JpkNaglowek
{
    private string dataOd = string.Empty;
    private string dataDo = string.Empty;

    [XmlIgnore]
    public DateTime DataDoDt { get; private set; } //value of DataDo as DateTime

    [XmlIgnore]
    public DateTime DataOdDt { get; private set; } //value of DataDo as DateTime

    [XmlElement(ElementName = "KodFormularza")]
    public JpkNaglowekKodFormularza KodFormularza { get; set; } = new JpkNaglowekKodFormularza(); //FormCode

    [XmlElement(ElementName = "WariantFormularza")]
    public string WariantFormularza { get; set; } //Variant

    [XmlElement(ElementName = "CelZlozenia")]
    public int CelZlozenia { get; set; } //Purpose

    [XmlElement(ElementName = "DataWytworzeniaJPK")]
    public DateTime DataWytworzeniaJPK { get; set; } //CreationDate - DateTime

    //DateFrom
    [XmlElement(ElementName = "DataOd")]
    public string DataOd 
    {
        get
        {
            return this.dataOd;
        }
        set
        {
            this.dataOd = value;

            //try to convert to DateTime
            DateTime dt = DateTime.MinValue;
            DateTime.TryParseExact(value, "yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out dt);

            //set value
            this.DataOdDt = dt;
        }
    }

    //DateTo
    [XmlElement(ElementName = "DataDo")]
    public string DataDo
    {
        get
        {
            return this.dataDo;
        }
        set
        {
            this.dataDo = value;

            //try to convert to DateTime
            DateTime dt = DateTime.MinValue;
            DateTime.TryParseExact(value, "yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out dt);

            //set value
            this.DataDoDt = dt;
        }
    }

    [XmlElement(ElementName = "KodUrzedu")]
    public string KodUrzedu { get; set; }
}

Note: In the code above you'll notice properties: DataDoDt and DataOdDt. They are public properties that hold the value of DataDo and DataOd respectively, as DateTime. By specifying [XmlIgnore] this property will be ignored during deserialization/serialization. In the XML, the format of the data is yyyy-MM-dd (ex: 2021-05-01), which is why it's necessary to specify the data type as a string. If the data type is specified as DateTime, when serialized the data in the XML file would look like yyyy-MM-ddTHH:mm:ss (ex: 2021-05-01T00:00:00)

Class: JpkNaglowekKodFormularza

public class JpkNaglowekKodFormularza
{
    [XmlAttribute(AttributeName = "kodSystemowy")]
    public string kodSystemowy { get; set; }

    [XmlAttribute(AttributeName = "wersjaSchemy")]
    public string wersjaSchemy { get; set; }

    [XmlText]
    public string Value { get; set; }
}

Class: JpkPodmiot1

public class JpkPodmiot1
{
    [XmlElement(ElementName = "IdentyfikatorPodmiotu")]
    public JpkPodmiot1IdentyfikatorPodmiotu IdentyfikatorPodmiotu { get; set; } = new JpkPodmiot1IdentyfikatorPodmiotu(); //SubjectId

    [XmlElement(ElementName = "AdresPodmiotu")]
    public JpkPodmiot1AdresPodmiotu AdresPodmiotu { get; set; } = new JpkPodmiot1AdresPodmiotu(); //Address
}

Class: JpkPodmiot1IdentyfikatorPodmiotu

[System.Xml.Serialization.XmlType(Namespace = "http://crd.gov.pl/xml/schematy/dziedzinowe/mf/2018/08/24/eD/DefinicjeTypy/")]
public class JpkPodmiot1IdentyfikatorPodmiotu
{
    [XmlElement(ElementName = "NIP")]
    public string NIP { get; set; }

    [XmlElement(ElementName = "PelnaNazwa")] 
    public string PelnaNazwa { get; set; } //FullName
}

In the code above, notice that the namespace was specified.

Class: JpkPodmiot1AdresPodmiotu

[System.Xml.Serialization.XmlType(Namespace = "http://crd.gov.pl/xml/schematy/dziedzinowe/mf/2018/08/24/eD/DefinicjeTypy/")]
public class JpkPodmiot1AdresPodmiotu
{
    [XmlElement(ElementName = "Wojewodztwo")]
    public string Wojewodztwo { get; set; } //Province

    [XmlElement(ElementName = "KodKraju")]
    public string KodKraju { get; set; } //CountryCode

    [XmlElement(ElementName = "Powiat")]
    public string Powiat { get; set; } //District

    [XmlElement(ElementName = "Gmina")]
    public string Gmina { get; set; } //Community

    [XmlElement(ElementName = "Ulica")]
    public string Ulica { get; set; } //StreetName

    [XmlElement(ElementName = "NrDomu")] 
    public Int32 NrDomu { get; set; } //HouseNumber

    [XmlElement(ElementName = "NrLokalu")]
    public Int32 NrLokalu { get; set; } //FlatNumber

    [XmlElement(ElementName = "Miejscowosc")]
    public string Miejscowosc { get; set; } //City

    [XmlElement(ElementName = "KodPocztowy")]
    public string KodPocztowy { get; set; } //PostalCode

}

In the code above, notice that the namespace was specified.

Here's a method that can be used to populate an instance of Jpk with some test data -- it's the data from the XML file that you specified above. It's useful for testing XML serialization.

CreateTestData

private Jpk CreateTestData()
{
    Jpk jpk = new Jpk();

    //Naglowek
    jpk.Naglowek.KodFormularza.kodSystemowy = "SomeCode";
    jpk.Naglowek.KodFormularza.wersjaSchemy = "1-0";
    jpk.Naglowek.KodFormularza.Value = "SomeCode";
    jpk.Naglowek.WariantFormularza = "3";
    jpk.Naglowek.CelZlozenia = 1;
    jpk.Naglowek.DataWytworzeniaJPK = DateTime.ParseExact("2021-06-30T15:57:53", "yyyy-MM-ddTHH:mm:ss", System.Globalization.CultureInfo.InvariantCulture); //"2021-06-30T15:57:53"; //ToDo: change to DateTime
    jpk.Naglowek.DataOd = "2021-05-01";
    jpk.Naglowek.DataDo = "2021-05-31";
    jpk.Naglowek.KodUrzedu = "0000";

    //Podmiot1
    jpk.Podmiot1.IdentyfikatorPodmiotu.NIP = "111111";
    jpk.Podmiot1.IdentyfikatorPodmiotu.PelnaNazwa = "SomeName";
    jpk.Podmiot1.AdresPodmiotu.Wojewodztwo = "voivodeship";
    jpk.Podmiot1.AdresPodmiotu.KodKraju = "PL";
    jpk.Podmiot1.AdresPodmiotu.Powiat = "Danzig";
    jpk.Podmiot1.AdresPodmiotu.Gmina = "Danzig";
    jpk.Podmiot1.AdresPodmiotu.Ulica = "SomeStreet";
    jpk.Podmiot1.AdresPodmiotu.NrDomu = 81;
    jpk.Podmiot1.AdresPodmiotu.NrLokalu = 1;
    jpk.Podmiot1.AdresPodmiotu.Miejscowosc = "Danzig";
    jpk.Podmiot1.AdresPodmiotu.KodPocztowy = "10-101";

    //Faktura
    JpkFaktura jpkFaktura = new JpkFaktura();
    jpkFaktura.KodWaluty = "PLN";
    jpkFaktura.P_1 = "2021-05-04";
    jpkFaktura.P_2A = "11 / 1111";
    jpkFaktura.P_3A = "Some Company";
    jpkFaktura.P_3B = "Some Address";
    jpkFaktura.P_3C = "Some Name";
    jpkFaktura.P_3D = "Some Other Address";
    jpkFaktura.P_4B = "Phone1";
    jpkFaktura.P_5B = "Phone2";
    jpkFaktura.P_13_1 = 1.00m; //need to use 'm' for decimal number
    jpkFaktura.P_14_1 = 1.25m; //need to use 'm' for decimal number
    jpkFaktura.P_15 = 0m; //need to use 'm' for decimal number
    jpkFaktura.P_16 = false;
    jpkFaktura.P_17 = false;
    jpkFaktura.P_18 = false;
    jpkFaktura.P_18A = false;
    jpkFaktura.P_19 = false;
    jpkFaktura.P_20 = false;
    jpkFaktura.P_21 = false;
    jpkFaktura.P_22 = false;
    jpkFaktura.P_23 = false;
    jpkFaktura.P_106E_2 = false;
    jpkFaktura.P_106E_3 = false;
    jpkFaktura.RodzajFaktury = "InvoiceType";

    //add
    jpk.Faktura.Add(jpkFaktura);

    //FakturaCtrl
    JpkFakturaCtrl jpkFakturaCtrl = new JpkFakturaCtrl();
    jpkFakturaCtrl.LiczbaFaktur = 1m; //need to use 'm' for decimal number
    jpkFakturaCtrl.WartoscFaktur = 2.00m; //need to use 'm' for decimal number

    //add
    jpk.FakturaCtrl.Add(jpkFakturaCtrl);

    //FakturaWiersz
    JpkFakturaWiersz jpkFakturaWiersz = new JpkFakturaWiersz();
    jpkFakturaWiersz.P_2B = "04/123";
    jpkFakturaWiersz.P_7 = "Text";
    jpkFakturaWiersz.P_8B = 1.000000m; //need to use 'm' for decimal number
    jpkFakturaWiersz.P_9A = 7.00m; //need to use 'm' for decimal number
    jpkFakturaWiersz.P_11 = 7.00m; //need to use 'm' for decimal number
    jpkFakturaWiersz.P_12 = 11;

    //add
    jpk.FakturaWiersz.Add(jpkFakturaWiersz);

    //FakturaWierszCtrl
    JpkFakturaWierszCtrl jpkFakturaWierszCtrl = new JpkFakturaWierszCtrl();
    jpkFakturaWierszCtrl.LiczbaWierszyFaktur = 11m; //need to use 'm' for decimal number
    jpkFakturaWierszCtrl.WartoscWierszyFaktur = 11.2m; //need to use 'm' for decimal number

    //add
    jpk.FakturaWierszCtrl.Add(jpkFakturaWierszCtrl);

    return jpk;
}

Usage:

Jpk jpk1 = CreateTestData();

For XML serialization, use the following:

public static void SerializeObjectToXMLFile(object obj, string xmlFilename)
{
    try
    {
        if (string.IsNullOrEmpty(xmlFilename))
        {
            return;
        }//if

        using (System.IO.TextWriter xmlStream = new System.IO.StreamWriter(xmlFilename))
        {
            //specify namespaces
            System.Xml.Serialization.XmlSerializerNamespaces ns = new System.Xml.Serialization.XmlSerializerNamespaces();
            ns.Add(string.Empty, "http://jpk.mf.gov.pl/wzor/2019/09/27/09271/");
            ns.Add("etd", "http://crd.gov.pl/xml/schematy/dziedzinowe/mf/2018/08/24/eD/DefinicjeTypy/");

            //create new instance
            System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(obj.GetType());

            //write XML to file
            serializer.Serialize(xmlStream, obj, ns);
        }
    }
    catch (Exception ex)
    {
        System.Diagnostics.Debug.WriteLine(ex.Message);
        throw ex;
    }
}

Usage:

Jpk jpk1 = CreateTestData();
SerializeObjectToXMLFile(jpk1, @"C:\Temp\Test.xml");

For deserialization, use the following code:

public static T DeserializeXMLFileToObject<T>(string xmlFilename)
{
    T rObject = default(T);

    try
    {

        if (string.IsNullOrEmpty(xmlFilename))
        {
            return default(T);
        }

        using (System.IO.StreamReader xmlStream = new System.IO.StreamReader(xmlFilename))
        {
            System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(T));
            rObject = (T)serializer.Deserialize(xmlStream);
        }
    }
    catch (Exception ex)
    {
        System.Diagnostics.Debug.WriteLine(ex.Message);
        throw ex;
    }

    return rObject;
}

Usage:

Jpk jpk1 = DeserializeXMLFileToObject<Jpk>(@"C:\Temp\Test.xml");

Upvotes: 1

Related Questions