Xmlserializer 到 C# 对象,存储原始 XML 元素 [英] Xmlserializer to C# object, store original XML element
问题描述
例如,是否可以将原始 XML 元素存储在 C# 类中?
Is it possible to store the original XML element in a C# class, for example?
原始 XML:
<data someattributea="" someattributeb="" someattributec="" />
C#
using System;
using System.Xml.Serialization;
using System.Collections.Generic;
namespace Xml2CSharp
{
[XmlRoot(ElementName="data")]
public class Data {
[XmlAttribute(AttributeName="someattributea")]
public string Someattributea { get; set; }
[XmlAttribute(AttributeName="someattributeb")]
public string Someattributeb { get; set; }
[XmlAttribute(AttributeName="someattributec")]
public string Someattributec { get; set; }
public sourceXML { get; set; } //this would return <data someattributea="" someattributeb="" someattributec="" />
}
}
我知道我可以再次反序列化该类,但某些 XML 对象在设计时未知.
I understand I could deserialize the class again but some XML objects are unknown at design time.
推荐答案
如果您确实需要捕获有关 元素的所有内容,包括元素名称和命名空间本身 转换为字符串文字,您需要实现
IXmlSerializable
并手动序列化您的 Data
类型.例如,这是一个原型实现:
If you really need to capture everything about the <data />
element including the element name and namespace itself into a string literal, you will need to implement IXmlSerializable
and serialize your Data
type manually. For instance, here is a prototype implementation:
[XmlRoot(ElementName = ElementName)]
public class Data : IXmlSerializable
{
public const string ElementName = "data";
XElement element = new XElement((XName)ElementName);
public string Someattributea
{
get { return (string)element.Attribute("someattributea"); }
set { element.SetAttribute("someattributea", value); }
}
public string Someattributeb
{
get { return (string)element.Attribute("someattributeb"); }
set { element.SetAttribute("someattributeb", value); }
}
public string Someattributec
{
get { return (string)element.Attribute("someattributec"); }
set { element.SetAttribute("someattributec", value); }
}
public string SourceXML
{
get
{
return element.ToString();
}
set
{
if (value == null)
throw new ArgumentNullException();
element = XElement.Parse(value);
}
}
#region IXmlSerializable Members
public XmlSchema GetSchema() { return null; }
public void ReadXml(XmlReader reader)
{
reader.MoveToContent();
element = (XElement)XNode.ReadFrom(reader);
}
public void WriteXml(XmlWriter writer)
{
foreach (var attr in element.Attributes())
writer.WriteAttributeString(attr.Name.LocalName, attr.Name.NamespaceName, attr.Value);
foreach (var child in element.Elements())
child.WriteTo(writer);
}
#endregion
}
public static class XElementExtensions
{
public static void SetAttribute(this XElement element, XName attributeName, string value)
{
var attr = element.Attribute(attributeName);
if (value == null)
{
if (attr != null)
attr.Remove();
}
else
{
if (attr == null)
element.Add(new XAttribute(attributeName, value));
else
attr.Value = value;
}
}
}
注意事项:
读取时,完整的 XML 被加载到一个
XElement
成员中,该成员可以使用 LINQ to XML.因此,原始格式可能会丢失.
When reading, the complete XML is loaded into an
XElement
member which can be queried using LINQ to XML. As a result the original formatting may get lost.
IXmlSerializable
很难正确实现.请参阅实现 IXmlSerializable 的正确方法? 和 如何正确实施 IXmlSerializable,了解有关如何执行的一些提示.
IXmlSerializable
is tricky to implement correctly. See Proper way to implement IXmlSerializable? and How to Implement IXmlSerializable Correctly for some tips on how to do it.
已知属性 Someattributea
、Someattributeb
和 Someattributec
现在成为对底层 XElement
的代理查找.
The known properties Someattributea
, Someattributeb
and Someattributec
now become surrogate lookups into the underlying XElement
.
工作 .Net fiddle 这里.
Working .Net fiddle here.
另一方面,如果您只需要捕获未知元素、属性和文本内容,则可以使用 [XmlAnyAttribute]
, [XmlAnyElement]
和 [XmlText]
(前两个在 这个答案等效于IExtensibleDataObject的XmlSerializer 来自 Marc Gravell).这种方法产生了一个更简单的 Data
版本:
If, on the other hand, you only need to capture unknown elements, attributes and text content, you can use [XmlAnyAttribute]
, [XmlAnyElement]
and [XmlText]
(the first two of which are suggested in this answer to XmlSerializer equivalent of IExtensibleDataObject by Marc Gravell). This approach results in a much simpler version of Data
:
[XmlRoot(ElementName = "data")]
public class Data
{
[XmlAttribute(AttributeName = "someattributea")]
public string Someattributea { get; set; }
[XmlAttribute(AttributeName = "someattributeb")]
public string Someattributeb { get; set; }
[XmlAttribute(AttributeName = "someattributec")]
public string Someattributec { get; set; }
[XmlAnyAttribute]
public XmlAttribute[] Attributes { get; set; }
[XmlAnyElement]
[XmlText] // Captures mixed content at the root level as well as child elements.
public XmlNode[] ChildNodes { get; set; }
}
工作 .Net fiddle #2 这里.
Working .Net fiddle #2 here.
这篇关于Xmlserializer 到 C# 对象,存储原始 XML 元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!