简体   繁体   中英

C# XML Serialization XMLElement Path

i am currently working on a project where i need the c# Xml Serialization.

My Problem: I havea class called ClassA. It has a Name Property which i would like to serialize in the Xml-File.

 public class ClassA : BaseClass
{
    [XmlElement("name")]
    public string Name
    {
        get { return GetProperty(() => Name); }
        set { SetProperty(() => Name, value); }
    }
}

So when i serialize this with this serializer

public class PetriNetXMLReader
{
    public void SaveToXML(PetriNetXML petriNet, string fileName)
    {
        System.Xml.Serialization.XmlSerializer writer =
       new System.Xml.Serialization.XmlSerializer(typeof(PetriNetXML));

           System.IO.FileStream file = System.IO.File.Create(fileName);

        writer.Serialize(file, petriNet);
        file.Close();
    }

    public PetriNetXML ReadFromXML(string fileName)
    {
        var fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);

        XmlSerializer deserializer = new XmlSerializer(typeof(PetriNetXML));
        return (PetriNetXML)deserializer.Deserialize(fileStream);



    }
}

i get a xml-file like this

<ClassA Id="5eda8e4c-0698-4e07-9d20-7985964786f9" >
  <name>Description</name>
</ClassA>

So my Question: I would like to have a xml like

 <ClassA Id="5eda8e4c-0698-4e07-9d20-7985964786f9" >
  <name><text>Description</text></name>
</ClassA>

How can i make this? I dont want to create a new class for the Name-Property..

Thanks :)

One possibility would be to turn Name into a complex class; for example:

[XmlElement("name")]
public MyText Name
{
    get { return GetProperty(() => Name); }
    set { SetProperty(() => Name, value); }
}

Then you could define MyText as:

public class MyText
{
    public string Text {get;set;}
}

You can use XMLReader:

ClassA a = new ClassA();

using (XmlTextReader reader = new XmlTextReader("books.xml"))
            {

                while (reader.Read())
                {
                    switch (reader.Name)
                    {
                        case "text":
                            //do something with this node, like:
                            a.Name = reader.Value;
                            break;
                    }
                }

            }

Alternatively, if you want to stick to object deserialization, you should get the exact matching-to-xml class, so refer to this:

XML2CSharp

You could implement custom serialisation, the ClassA would need to implement ISerializable . Alternatively implement the custom serialization using ISerializationSurrogate and its related interfaces.

However that is not something I'd do. Its likely going to be much more complicated than having a wrapper class for Name.

You can customize serialization process. For example ClassA could be decorated with attribute:

public class ClassA : BaseClass, IXmlSerializable
{
    [XmlElement("name/text")]
    public string Name
    {
        get { return GetProperty(() => Name); }
        set { SetProperty(() => Name, value); }
    }
}

Then the BaseClass class should implement IXmlSerializable like this:

public class BaseClass : IXmlSerializable
{
    public XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(XmlReader reader)
    {
        foreach (PropertyInfo propertyInfo in this.GetType().GetProperties())
        {
            XmlElementAttribute elementAttribute = propertyInfo.GetCustomAttribute<XmlElementAttribute>(true);

            if (elementAttribute != null)
            {
                string[] elementNames = elementAttribute.ElementName.Split('/', '\\');

                foreach (string elementName in elementNames)
                {
                    reader.ReadStartElement(elementName);
                }

                propertyInfo.SetValue(this, reader.ReadContentAsString());

                foreach (string elementName in elementNames)
                {
                    reader.ReadEndElement();
                }
            }
        }
    }

    public void WriteXml(XmlWriter writer)
    {
        foreach (PropertyInfo propertyInfo in this.GetType().GetProperties())
        {
            XmlElementAttribute elementAttribute = propertyInfo.GetCustomAttribute<XmlElementAttribute>(true);

            if (elementAttribute != null)
            {
                string[] elementNames = elementAttribute.ElementName.Split('/', '\\');

                foreach (string elementName in elementNames)
                {
                    writer.WriteStartElement(elementName);
                }

                writer.WriteString(propertyInfo.GetValue(this).ToString());

                foreach (string elementName in elementNames)
                {
                    writer.WriteEndElement();
                }
            }
        }
    }

    protected string GetProperty(Func<string> f)
    {
        return "text-value";
    }

    protected void SetProperty<T>(Func<T> f, T value)
    {
    }
}

The result of serialization will be:

<ClassA>
  <name>
    <text>text-value</text>
  </name>
</ClassA>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM