Como uso o mesmo XMLAttribute para várias propriedades?

Oct 20 2020

Eu tenho a classe de wrapper abaixo.

[Serializable]
    public class Vehicle
    {
        public string Make { get; set; }
        public string Model { get; set; }
        public string Year { get; set; }

        public static void Serialize()
        {
            string fileName = "data.xml";
            Console.WriteLine("Enter Make, Model & Year");
            var vehicle = new Vehicle
            {
                Make = "Honda",
                Model = "H1245",
                Year = "1975"
            };
            //Serialization
            var document = new XmlDocument();
            var xml = new XmlSerializer(typeof(Vehicle));
            TextWriter writer = new StreamWriter(fileName);
            xml.Serialize(writer, vehicle);
            writer.Close();
            //Attribution
            if (File.Exists(fileName))
            {
                document.Load(fileName);
                var nodeList = document.SelectNodes("//Vehicle//*");

                var attribute1 = document.CreateAttribute("applicableTo");
                attribute1.Value = "Common";
                var attribute2 = document.CreateAttribute("applicableTo");
                attribute2.Value = "Cfpd";
                var attribute3 = document.CreateAttribute("applicableTo");
                attribute3.Value = "Markel";

                for (int i = 0; i < nodeList.Count; i++)
                {
                    if (nodeList[i].InnerText.Equals("Honda"))
                        ((XmlElement)(nodeList[i])).SetAttributeNode(attribute1);
                    if (nodeList[i].InnerText.Equals("H1245"))
                        ((XmlElement)(nodeList[i])).SetAttributeNode(attribute2);
                    if (nodeList[i].InnerText.Equals("1975"))
                        ((XmlElement)(nodeList[i])).SetAttributeNode(attribute3);
                }
                document.Save(Console.Out);
            }
        }

Minha saída desejada é a seguinte. No entanto, obtenho a mesma saída que o XML abaixo.

<?xml version="1.0" encoding="utf-8"?>
<Vehicle xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Make applicableTo="Common">Honda</Make>
  <Model applicableTo="Cfpd">H1245</Model>
  <Year applicableTo="Markel">1975</Year>
</Vehicle>

Aqui vai meu problema,

Como faço para ter o atributo applicableToajustado para fazer propriedades, modelo e ano sem ter que criá-los como attribute1, attribute2, attribute3ainda valores a serem atribuídos com base na entrada atribuído a propriedades? O que significa que, se Makefor, Hondaa saída XML deve ser <Make applicableTo="Common">Honda</Make>e da mesma forma.

XMLAttribute só pode ser definido para uma propriedade em uma classe, o que não é ideal ao lidar com um grande número de classes. E então SetAttributeNodelança um erro -

O nó 'Atributo' não pode ser inserido porque já é um atributo de outro elemento.

Por favor ajude.

Observe que o formato da minha saída não deve mudar.

Respostas

1 jdweng Oct 20 2020 at 09:17

Usando Xml Linq:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Data;

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";

        static void Main(string[] args)
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("Make", typeof(string));
            dt.Columns.Add("Make Attribute", typeof(string));
            dt.Columns.Add("Model", typeof(string));
            dt.Columns.Add("Model Attribute", typeof(string));
            dt.Columns.Add("Year", typeof(string));
            dt.Columns.Add("Year Attribute", typeof(string));

            dt.Rows.Add(new object[] { "Honda", "Common", "H1245", "Cfpd", "1975", "Markel" });
            dt.Rows.Add(new object[] { "Honda", "Common", "H1245", "Cfpd", "1975", "Markel" });
            dt.Rows.Add(new object[] { "Honda", "Common", "H1245", "Cfpd", "1975", "Markel" });
            Vehicle.Serialize(dt, FILENAME);
        }
    }
    public class Vehicle
    {
        public static void Serialize(DataTable dt, string fileName)
        {
            string ident = 
                "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                "<Vehicles xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">" +
                "</Vehicles>";

            XDocument doc = XDocument.Parse(ident);
            XElement xVehicles = doc.Root;

            foreach (DataRow row in dt.AsEnumerable())
            {
                XElement xVehicle = new XElement("Vehicle", new object[] {
                    new XElement("Make", new object[] {new XAttribute("applicableTo", row.Field<string>("Make Attribute")), row.Field<string>("Make")}),
                    new XElement("Make", new object[] {new XAttribute("applicableTo", row.Field<string>("Model Attribute")), row.Field<string>("Model")}),
                    new XElement("Make", new object[] {new XAttribute("applicableTo", row.Field<string>("Year Attribute")), row.Field<string>("Year")})
                });
                xVehicles.Add(xVehicle);
            }
            doc.Save(fileName);
        }
    }
}