0

I need to create xml with certain looks using serializer:

                EPIT11V21 curpit11 = new EPIT11V21(curdec.id);

                XmlSerializer serializer = new XmlSerializer(typeof(EPIT11V21));
                using (TextWriter writer = new StreamWriter(@"F:\xml\Xml.xml"))
                {
                    serializer.Serialize(writer, curpit11);
                }

where my EPIT11V21 class is declared:

[XmlRoot("Deklaracja")]
public class EPIT11V21
{
     public EPIT11V21()        {        }

    public EPIT11V21(int XPDeclarationID)
    {
            this.Pouczenie = "Za uchybienie obowiązkom płatnika grozi odpowiedzialność przewidziana w Kodeksie karnym skarbowym.";
            //this.Zalaczniki = "";
        }

    }

    public Podmiot1PIT11V21 Podmiot1 = new Podmiot1PIT11V21();
    public String Pouczenie { get; set; }
    public String Zalaczniki{ get; set; }

with subclasses:

public class Podmiot1PIT11V21
{
    public Podmiot1PIT11V21(){}
    [XmlAttribute("rola")]
    public string rola = "Płatnik";
    public OsobaNiefizycznaPIT11V21 OsobaNieFizyczna = new OsobaNiefizycznaPIT11V21();
}


public class OsobaNiefizycznaPIT11V21
{
    public OsobaNiefizycznaPIT11V21(){}
    public string NIP = "0000000000";
    public string PelnaNazwa = "XXXXXXXX";
}

How to decorate its parts to get such an effect:

<?xml version="1.0" encoding="UTF-8"?>
<Deklaracja xsi:schemaLocation="http://crd.gov.pl/wzor/2014/12/08/1887/ http://crd.gov.pl/wzor/2014/12/08/1887/schemat.xsd" xmlns="http://crd.gov.pl/wzor/2014/12/08/1887/" xmlns:etd="http://crd.gov.pl/xml/schematy/dziedzinowe/mf/2011/06/21/eD/DefinicjeTypy/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:zzu="http://crd.gov.pl/xml/schematy/dziedzinowe/mf/2011/10/07/eD/ORDZU/">
    <Podmiot1 rola="Płatnik">
        <etd:OsobaNiefizyczna>
            <etd:NIP>0000000000</etd:NIP>
            <etd:PelnaNazwa>XXXXXXXXXXXXX</etd:PelnaNazwa>
        </etd:OsobaNiefizyczna>
    </Podmiot1>
    <Zalaczniki>
    </Zalaczniki>
</Deklaracja>

i just get in second line:

<Deklaracja xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">

also how to decorate that clasess so to get etd: prefix as in example ??

romeck
  • 23
  • 5

2 Answers2

2

Your question has many different components:

  1. In order to make the property OsobaNiefizyczna go in the correct namespace, decorate it with XmlElement and set the Namespace property correctly.

  2. In order to add additional namespaces to the root document object, attach the [XmlNamespaceDeclarations] attribute to a public XmlSerializerNamespaces xmlsn synthetic property returning the namespaces. Also set the XmlRootAttribute.Namespace properly on the root object.

  3. To make the root object have a schemaLocation attribute, you must add a synthetic property along the lines of the answer in How to add xsi schemalocation to root c # object XmlSerializer -- but use a property instead of a field. If you use a field you will actually add to the footprint of your class in memory.

  4. To omit the standard xsd namespace (though I recommend you do not), use the XmlSerializer.Serialize(XmlWriter, Object, XmlSerializerNamespaces) method and pass in only the namespaces you want to see.

  5. To make an empty Zalaczniki element show up, you need to set the property value to string.Empty.

Putting these together we get:

public static class NameSpaces
{
    static readonly XmlSerializerNamespaces namespaces;

    static NameSpaces()
    {
        namespaces = new XmlSerializerNamespaces();
        namespaces.Add("", NameSpaces.Default);
        namespaces.Add("xsi", NameSpaces.Xsi);
        namespaces.Add("etd", NameSpaces.Etd);
        namespaces.Add("zzu", NameSpaces.Zzu);
    }

    public static XmlSerializerNamespaces XmlSerializerNamespaces
    {
        get
        {
            return namespaces;
        }
    }

    public const string Default = "http://crd.gov.pl/wzor/2014/12/08/1887/";
    public const string Etd = "http://crd.gov.pl/xml/schematy/dziedzinowe/mf/2011/06/21/eD/DefinicjeTypy/";
    public const string Xsi = "http://www.w3.org/2001/XMLSchema-instance";
    public const string Zzu = "http://crd.gov.pl/xml/schematy/dziedzinowe/mf/2011/10/07/eD/ORDZU/";
    public const string SchemaLocation = "http://crd.gov.pl/wzor/2014/12/08/1887/ http://crd.gov.pl/wzor/2014/12/08/1887/schemat.xsd";
}

[XmlRoot("Deklaracja", Namespace = NameSpaces.Default)]
public class EPIT11V21
{
    public EPIT11V21() {
        this.Zalaczniki = string.Empty;
    }

    public EPIT11V21(int XPDeclarationID) : this()
    {
        this.Pouczenie = "Za uchybienie obowiązkom płatnika grozi odpowiedzialność przewidziana w Kodeksie karnym skarbowym.";
    }

    [XmlAttribute("schemaLocation", Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
    public string XSDSchemaLocation
    {
        get
        {
            return NameSpaces.SchemaLocation;
        }
        set {
            // Do nothing - fake property.
        }
    }

    public Podmiot1PIT11V21 Podmiot1 = new Podmiot1PIT11V21();

    public String Pouczenie { get; set; }

    public String Zalaczniki { get; set; }

    [XmlNamespaceDeclarations]
    public XmlSerializerNamespaces xmlsn
    {
        get
        {
            return NameSpaces.XmlSerializerNamespaces;
        }
        set { 
            // Do nothing - fake property.
        }
    }
}

public class Podmiot1PIT11V21
{
    public Podmiot1PIT11V21() { }

    [XmlAttribute("rola")]
    public string rola = "Płatnik";

    [XmlElement("OsobaNieFizyczna", Namespace = NameSpaces.Etd)]
    public OsobaNiefizycznaPIT11V21 OsobaNieFizyczna = new OsobaNiefizycznaPIT11V21();
}

public class OsobaNiefizycznaPIT11V21
{
    public OsobaNiefizycznaPIT11V21() { }
    public string NIP = "0000000000";
    public string PelnaNazwa = "XXXXXXXX";
}

And, to test:

public static class TestClass
{
    public static void Test()
    {
        var curpit11 = new EPIT11V21(10101);

        var xml = XmlSerializationHelper.GetXml(curpit11, NameSpaces.XmlSerializerNamespaces);
        Debug.WriteLine(xml);
    }
}

public static class XmlSerializationHelper
{
    public static string GetXml<T>(this T obj)
    {
        return GetXml(obj, false);
    }

    public static string GetXml<T>(this T obj, bool omitNamespace)
    {
        return GetXml(obj, new XmlSerializer(obj.GetType()), omitNamespace);
    }

    public static string GetXml<T>(this T obj, XmlSerializer serializer)
    {
        return GetXml(obj, serializer, false);
    }

    public static string GetXml<T>(T obj, XmlSerializer serializer, bool omitStandardNamespaces)
    {
        XmlSerializerNamespaces ns = null;
        if (omitStandardNamespaces)
        {
            ns = new XmlSerializerNamespaces();
            ns.Add("", ""); // Disable the xmlns:xsi and xmlns:xsd lines.
        }
        return GetXml(obj, serializer, ns);
    }

    public static string GetXml<T>(T obj, XmlSerializerNamespaces ns)
    {
        return GetXml(obj, new XmlSerializer(obj.GetType()), ns);
    }

    public static string GetXml<T>(T obj, XmlSerializer serializer, XmlSerializerNamespaces ns)
    {
        using (var textWriter = new StringWriter())
        {
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;        // For cosmetic purposes.
            settings.IndentChars = "    "; // For cosmetic purposes.
            using (var xmlWriter = XmlWriter.Create(textWriter, settings))
            {
                if (ns != null)
                    serializer.Serialize(xmlWriter, obj, ns);
                else
                    serializer.Serialize(xmlWriter, obj);
            }
            return textWriter.ToString();
        }
    }
}

Produces

<Deklaracja xmlns:zzu="http://crd.gov.pl/xml/schematy/dziedzinowe/mf/2011/10/07/eD/ORDZU/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:etd="http://crd.gov.pl/xml/schematy/dziedzinowe/mf/2011/06/21/eD/DefinicjeTypy/" xsi:schemaLocation="http://crd.gov.pl/wzor/2014/12/08/1887/ http://crd.gov.pl/wzor/2014/12/08/1887/schemat.xsd" xmlns="http://crd.gov.pl/wzor/2014/12/08/1887/">
    <Podmiot1 rola="Płatnik">
        <etd:OsobaNieFizyczna>
            <etd:NIP>0000000000</etd:NIP>
            <etd:PelnaNazwa>XXXXXXXX</etd:PelnaNazwa>
        </etd:OsobaNieFizyczna>
    </Podmiot1>
    <Pouczenie>Za uchybienie obowiązkom płatnika grozi odpowiedzialność przewidziana w Kodeksie karnym skarbowym.</Pouczenie>
<Zalaczniki />
</Deklaracja>
dbc
  • 104,963
  • 20
  • 228
  • 340
  • thanks for quick response i will test it . One more question couse i do not know good xml build, how can i change that code to have order of attributes for Deklaracja like i give in example. In your output they are in different order . – romeck Feb 11 '15 at 06:08
  • As far as I know you can't control the order of namespace attributes with `XmlSerializer`. However, according to the [XML specification Section 3.1](http://www.w3.org/TR/REC-xml/#sec-starttags), "the order of attribute specifications in a start-tag or empty-element tag is not significant.". So it shouldn't matter. But if you *must* have the attributes in a specific order (for political reasons?) you may have to reload the XML into an `XDocument` and follow the algorithm here: https://stackoverflow.com/questions/28420906/xdocument-save-removing-node-prefixes/28424698#28424698 – dbc Feb 11 '15 at 06:13
0

I change my code like this:

            Declaration curdec = gVDeclarations.GetRow(i) as Declaration;
            EPIT11V21 curpit11 = new EPIT11V21(curdec.id);

            XmlSerializerNamespaces ns = new XmlSerializerNamespaces();

            ns.Add("schemaLocation", @"http://crd.gov.pl/wzor/2014/12/08/1887/ http://crd.gov.pl/wzor/2014/12/08/1887/schemat.xsd");
            ns.Add("xmlns", @"http://crd.gov.pl/wzor/2014/12/08/1887/");
            ns.Add("etd", @"http://crd.gov.pl/xml/schematy/dziedzinowe/mf/2011/06/21/eD/DefinicjeTypy/");
            ns.Add("xsi", @"http://www.w3.org/2001/XMLSchema-instance");
            ns.Add("zzu", @"http://crd.gov.pl/xml/schematy/dziedzinowe/mf/2011/10/07/eD/ORDZU/");

            XmlSerializer serializer = new XmlSerializer(typeof(EPIT11V21));
            using (TextWriter writer = new StreamWriter(@"F:\xml\Xml.xml"))
            {
                serializer.Serialize(writer, curpit11,ns);
            }

and to Deklaracja sub clases

public class Podmiot1PIT11V21
{
    public Podmiot1PIT11V21(){}
    [XmlAttribute("rola")]
    public string rola = "Płatnik";
    [XmlElement("OsobaNieFizyczna", Namespace = "http://crd.gov.pl/xml/schematy/dziedzinowe/mf/2011/06/21/eD/DefinicjeTypy/")]
    public OsobaNiefizycznaPIT11V21 OsobaNieFizyczna = new OsobaNiefizycznaPIT11V21();
}

I get almoast what iwant but 2nd line which i get:

    <Deklaracja 
xmlns:xmlns="http://crd.gov.pl/wzor/2014/12/08/1887/" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:schemaLocation="http://crd.gov.pl/wzor/2014/12/08/1887/ http://crd.gov.pl/wzor/2014/12/08/1887/schemat.xsd" 
xmlns:zzu="http://crd.gov.pl/xml/schematy/dziedzinowe/mf/2011/10/07/eD/ORDZU/" 
xmlns:etd="http://crd.gov.pl/xml/schematy/dziedzinowe/mf/2011/06/21/eD/DefinicjeTypy/">

is there a way to just change "ns" to change that line in easy way ?

romeck
  • 23
  • 5
  • `schemaLocation` is not a namespace. You can't add it using a `XmlSerializerNamespaces`. See here: https://stackoverflow.com/questions/27530334/xml-serialization-namespaces – dbc Feb 11 '15 at 06:28
  • Also, it's recommended to ask [one question per question](http://meta.stackexchange.com/questions/39223/one-post-with-multiple-questions-or-multiple-posts). If you ask a second question in a self-answer to your own question, very few people will notice. – dbc Feb 11 '15 at 06:29
  • Suggest you avoid duplicating long string constants in your code. The `NameSpaces` static class was designed to centralize them. – dbc Feb 11 '15 at 06:31
  • Thanks for info im kinda new here :). Could you please add more code to complete how to use that static class you create. (Main function) im new into programing and some things are unknown to me(or im not sure if i do it right and if im right the use of your example should be : Testclass.Test(); right? – romeck Feb 11 '15 at 20:02
  • I edited my answer to separate out a `XmlSerializationHelper` class that generates formatted XML with specified namespaces. Then call the methods there once you have an allocated `EPIT11V21`. Not sure what else you would need. – dbc Feb 11 '15 at 21:35
  • HI i do as you write but i have strange thing, now in first line i have: what do i need to do to change it to : with utf-16 application cant even see that xml. – romeck Feb 12 '15 at 22:16
  • to force a "utf-8" in the string output, follow the answer here: https://stackoverflow.com/questions/3862063/serializing-an-object-as-utf-8-xml-in-net/3862106#3862106 – dbc Feb 12 '15 at 23:07
  • How can i change order in: – romeck Feb 13 '15 at 08:55