XML 元素和属性的多个名称 [英] Multiple Names for XML Elements and Attributes
问题描述
不是这个的重复: 这已被标记为与我添加到现有 StackOverflow 问题和解决方案的链接重复.这不是重复的,因为该问题专门针对 XmlElements.我正在寻找一种方法来塑造解决方案的工作使用 XmlAttributes 以及 XmlElements.
NOT A DUPLICATE OF THIS: This has been flagged as a duplicate of the link that I added to an existing StackOverflow Question and Solution. This is not a duplicate as that question specifically deals with XmlElements. I am looking for a way to mould that solution to work with XmlAttributes as well as XmlElements.
我正在构建一个与返回 XML 的 Web 服务交互的类库.此 Web 服务附加到文档管理系统.我为系统中的每种类型的实体(文件夹、文档、用户等)构建了一个对象.我目前有一个问题,其中有三个不同的操作返回指定目录中的文档列表.每个操作都以不同的格式返回文档元数据.
I am building a Class Library that interacts with Web Service that returns XML. This Web Service is attached to a Document Management System. I have built an object for each type of entity that is in the system (Folder, Document, User, etc.). I currently have an issue where there are three different operations that return a list of documents that are in a specified directory. Each operation returns the document metadata in a different format.
<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 的同一个对象,而不是为每个项目返回不同的类型.
All of these elements are for the exact same document. I am wanting to deserialise each of these into the same object called Document rather than return a different type for each item.
我在这里找到了一个很好的解决方案,用于处理元素的同义词.唯一的问题是它没有显示我如何为属性添加同义词.
I found a great solution here for working with synonyms for elements. The only problem is that it does not show how I could add synonyms in for Attributes.
我尝试创建另一个为 UnknownAttribute
事件调用的方法,但我没有成功.该方法只是上一个链接中的 SynonymHandler 方法的副本,但我对其进行了略微更改.
I have attempted to create another method that is called for the UnknownAttribute
event but I have not been successful. The method is just a copy of the SynonymHandler method in the previous link, but I have altered it slightly.
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);
}
}
我可能做错了,但我真的希望我能够避免在每种情况下手动处理属性.任何帮助表示赞赏.
I am probably going about it wrong, but I was really hoping that I would be able to avoid manually handling the attributes in each case. Any help is appreciated.
当涉及到其他类型(例如文件夹)时,我也有同样的问题,所以我正在寻找一个单一的解决方案,而不必为发生这种情况的每个对象创建一个单独的反序列化器到.这就是我非常喜欢 SynonymAttribute : Attribute
解决方案的原因.它将所有重要信息放在一起,并使用 Reflection 找到我要查找的属性.
I also have the same issue when it comes to other types (e.g. Folders) so I am looking for a single solution rather than having to create a separate deserialiser for each object that this happens to. That is why I really liked the SynonymAttribute : Attribute
solution. It kept all the important information together and used Reflection to find which Attribute I was looking for.
推荐答案
使用 xml linq 可以使用以下代码:
Using xml linq you can use following code :
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; }
}
}
这篇关于XML 元素和属性的多个名称的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!