Несколько имен для элементов и атрибутов XML - PullRequest
0 голосов
/ 11 июня 2018

НЕ ДУБЛИКАТ ЭТОГО : Это помечено как дубликат ссылки, которую я добавил в существующий вопрос и решение StackOverflow.Это не дубликат, так как этот вопрос конкретно касается XmlElements.Я ищу способ формирования этого решения для работы с XmlAttributes, а также с XmlElements.


Я создаю библиотеку классов, которая взаимодействует с веб-службой, которая возвращает XML.Этот веб-сервис подключен к системе управления документами.Я построил объект для каждого типа объекта, который находится в системе (папка, документ, пользователь и т. Д.).В настоящее время у меня есть проблема, где есть три разные операции, которые возвращают список документов, которые находятся в указанном каталоге.Каждая операция возвращает метаданные документа в другом формате.

<d id="1104" name="Intro.pdf" cdate="2018-06-08 13:27:05" size="188481" />

<d id="1104" n="Intro.pdf" s="188481" />

<document DocumentID="1104" Name="Intro.pdf" CreationDate="2018-06-08 13:27:05" Size="188481" />

Все эти элементы предназначены для одного и того же документа.Я хочу десериализовать каждый из них в один и тот же объект с именем Document, а не возвращать разные типы для каждого элемента.

Я нашел отличное решение здесь для работы с синонимами для элементов.Единственная проблема состоит в том, что он не показывает, как я мог бы добавить синонимы для атрибутов.

Я попытался создать другой метод, который вызывается для события UnknownAttribute, но я не увенчался успехом.Метод является просто копией метода SynonymHandler в предыдущей ссылке, но я немного его изменил.

protected void AttributeSynonymHandler(object sender, XmlAttributeEventArgs e)
    {
        //this part works as it returns the correct property to me
        var member = SynonymsAttribute.GetMember(e.ObjectBeingDeserialized, e.Attr.Name);
        Type memberType;

        if (member != null && member is FieldInfo)
            memberType = ((FieldInfo)member).FieldType;
        else if (member != null && member is PropertyInfo)
            memberType = ((PropertyInfo)member).PropertyType;
        else
            return;

        if (member != null)
        {
            //this is where the logic falls down, mainly because I don't have the original element anymore.
            object value;
            XmlSynonymDeserializer serializer = new XmlSynonymDeserializer(memberType, new XmlRootAttribute(e.Attr.Name));
            using (System.IO.StringReader reader = new System.IO.StringReader(e.Attr.OuterXml))
                value = serializer.Deserialize(reader);

            if (member is FieldInfo)
                ((FieldInfo)member).SetValue(e.ObjectBeingDeserialized, value);
            else if (member is PropertyInfo)
                ((PropertyInfo)member).SetValue(e.ObjectBeingDeserialized, value);
        }
    }

Я, вероятно, ошибаюсь, но я действительно надеялсячто я смог бы избежать ручной обработки атрибутов в каждом случае.Любая помощь приветствуется.

РЕДАКТИРОВАТЬ: У меня также есть такая же проблема, когда речь идет о других типах (например, папки), поэтому я ищу одно решение, а не создавать отдельноедесериализатор для каждого объекта, с которым это происходит.Вот почему мне очень понравилось решение SynonymAttribute : Attribute.Он собрал всю важную информацию вместе и использовал Reflection, чтобы найти, какой атрибут я искал.

1 Ответ

0 голосов
/ 11 июня 2018

Используя xml linq, вы можете использовать следующий код:

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


namespace ConsoleApplication48
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(FILENAME);

            var groups = (from d in doc.Descendants("d")
                             join xdoc in doc.Descendants("document") on (string)d.Attribute("id") equals (string)xdoc.Attribute("DocumentID")
                             select new List<XElement> { d, xdoc })
                             .GroupBy(x => (string)x.FirstOrDefault().Attribute("id"))
                             .Select(x => x.SelectMany(y => y).ToList())
                             .ToList();
            List<Document> documents = new List<Document>();
            foreach (var group in groups)
            {
                Document newDoc = new Document();
                documents.Add(newDoc);
                foreach (XElement element in group)
                {
                    foreach (XAttribute attribute in element.Attributes())
                    {
                        switch (attribute.Name.LocalName.ToUpper())
                        {
                            case "ID" :
                                newDoc.id = (string)attribute;
                                break;
                            case "DOCUMENTID":
                                newDoc.id = (string)attribute;
                                break;
                            case "NAME":
                                newDoc.name = (string)attribute;
                                break;
                            case "N":
                                newDoc.name = (string)attribute;
                                break;
                            case "CDATE":
                                newDoc.date = (DateTime)attribute;
                                break;
                            case "CREATIONDATE":
                                newDoc.date = (DateTime)attribute;
                                break;
                            case "SIZE":
                                newDoc.size = (long)attribute;
                                break;
                            case "S":
                                newDoc.size = (long)attribute;
                                break;
                            default :
                                break;

                        }
                    }
                }

            }
        }
    }
    public class Document
    {
        public string id { get; set; }
        public string name {get; set; }
        public long size { get; set; }
        public DateTime date { get; set; }

    }
}
...