反序列化自定义 XML 时出现 InvalidOperationException(缺少命名空间)

Posted

技术标签:

【中文标题】反序列化自定义 XML 时出现 InvalidOperationException(缺少命名空间)【英文标题】:InvalidOperationException when deserializing custom XML (lack of namespace) 【发布时间】:2021-09-13 19:57:04 【问题描述】:

我有一个以以下根开头的 XML 文档:

<?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>

它有大写字母。我对它的定义没有影响,我需要自己调整。

我已经为它写了一个类:

    [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; 
    

我有反序列化它的代码:

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

当我运行这段代码时,我得到了

System.InvalidOperationException: 'XML 文档 (2, 2) 中存在错误。' InvalidOperationException:不是预期的。

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 ensured that the XmlRoot element has the exact capitalized version I encounter in the file I put the namespace in I tried adding Serializable, no changes I ensured I pass the XmlRootAttribute to the serializer constructor

我的蜘蛛感觉告诉我它可能与第二个定义有关,但我不确定如何处理它。我试图删除它(出于科学目的),但它并没有改变响应。

我还有什么遗漏的吗?

剧透警告:这(也)是关于第二个命名空间定义的。值得庆幸的是,接受的答案向我展示了如何声明它,以及如何处理 etd 部分。那,以及从代码中删除new XmlRootAttribute("JPK")

【问题讨论】:

您的代码太少而无用。请提供完整的有效示例 XML 文件,而不仅仅是第一行。 已添加。希望这会有所帮助。 【参考方案1】:

在尝试调试 XML 反序列化问题时,我发现序列化我使用一些示例数据创建的类很有帮助。然后,我检查我序列化的数据(保存到 XML 文件)是否与我试图反序列化的 XML 文件相同。

在您发布的 XML 数据中,Faktura 内的内容如下:

   <P_15>SomeDecimalNumber</P_15>

那么在JpkInvoice类中如下:

   public decimal P_15  get; set; 

这是一个问题,因为 XML 文件中的值是 string,而属性被声明为 decimal。属性数据类型需要为 string,或者 XML 文件中的值需要更改为有效的十进制值。为了测试,在 XML 中,我将 &lt;P_15&gt;SomeDecimalNumber&lt;/P_15&gt; 替换为 &lt;P_15&gt;0&lt;/P_15&gt;

我已经使用您提供的 XML 测试了以下代码 - 使用上述 XML 数据修改。我更改了属性名称以匹配 XML 文件中的内容,因为我发现这样更容易。如果您愿意,可以重命名它们。另外,我更喜欢使用 List 而不是数组,因此您也会在代码中注意到这一点。

在下面的代码中,以下 using 语句是必需的:

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

创建一个类(名称:Jpk)

类: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


类: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; 

注意:在上面的代码中,您会注意到一个名为 P_1Dt 的属性。这是一个公共属性,将P_1 的值保存为DateTime。通过指定[XmlIgnore],此属性将在反序列化/序列化期间被忽略。在 XML 中,数据的格式为yyyy-MM-dd(例如:2021-05-01),这就是为什么需要将数据类型指定为字符串的原因。如果数据类型指定为DateTime,则在序列化后,XML 文件中的数据将类似于yyyy-MM-ddTHH:mm:ss(例如:2021-05-01T00:00:00)

类:JpkFakturaCtrl

public class JpkFakturaCtrl

    [XmlElement]
    public decimal LiczbaFaktur  get; set; 

    [XmlElement]
    public decimal WartoscFaktur  get; set; 

类: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; 

类:JpkFakturaWierszCtrl

public class JpkFakturaWierszCtrl

    [XmlElement]
    public decimal LiczbaWierszyFaktur  get; set; 

    [XmlElement]
    public decimal WartoscWierszyFaktur  get; set; 

类: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; 

注意:在上面的代码中,您会注意到属性:DataDoDtDataOdDt。它们是公共属性,分别持有DataDoDataOd 的值,如DateTime。通过指定[XmlIgnore],该属性将在反序列化/序列化期间被忽略。在 XML 中,数据的格式是yyyy-MM-dd(例如:2021-05-01),这就是为什么需要将数据类型指定为字符串的原因。如果数据类型指定为DateTime,则在序列化后,XML 文件中的数据将类似于yyyy-MM-ddTHH:mm:ss(例如:2021-05-01T00:00:00)

类: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; 

类: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

类: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

在上面的代码中,注意命名空间被指定了。

类: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


在上面的代码中,注意命名空间被指定了。

这是一种方法,可用于使用一些测试数据填充Jpk 的实例——它是您在上面指定的 XML 文件中的数据。它对于测试 XML 序列化很有用。

创建测试数据

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;

用法

Jpk jpk1 = CreateTestData();

对于 XML 序列化,请使用以下内容:

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;
    

用法

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

对于反序列化,使用以下代码:

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;

用法

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

【讨论】:

事实上,该小数被假定为小数,而不是字符串;-) 删除 new XmlRootAttribute("JPK") 并将命名空间添加到子类就可以了。

以上是关于反序列化自定义 XML 时出现 InvalidOperationException(缺少命名空间)的主要内容,如果未能解决你的问题,请参考以下文章

反序列化包含简单引用实体的xml文件时出现异常

C# Xml 反序列化错误

如何自定义 SpringWebFlux WebClient xml+rss JAXB 反序列化?

Spring Boot:使用自定义序列化器 + 反序列化器消费和生成 XML

Newtonsoft.Json.JsonSerializationException:'反序列化对象时出现意外标记:使用动态对象注释

如何从不使用 XElement 的自定义 XML 序列化/反序列化为 `Dictionary<int, string>`?