-
23-08-2019 - |
题
我有一个情况我有,我不想修改XML文件。 在的XElement类AddAnnotation功能提供了一个选项,以只添加存储器数据这不是XML的序列化,而不是一部分。
我希望能够将这些注释保存(例如:另一个XML文件),然后才能得到相同的对象,我不得不反序列化两个XML和注释。
我不想改变原有的XML,这就是我使用注释的原因。
要总结,我希望能够自定义的数据添加到XML文件。此数据将不会是XML的一部分,当我序列化或这将是XML的一部分,但是我将能够很容易地检索原始XML。
你有什么建议,我该怎么做这样的事情?
修改强>我应该使用XML处理指令?旨在用于这种用途的处理指令?
解决方案
这听起来好像最简单的方法是使用常规节点,但在不同的XML命名空间 - 即
<foo standardAttrubute="abc" myData:customAttribute="def">
<standardElement>ghi</standardElement >
<myData:customElement>jkl</myData:customElement>
</foo>
(其中myData
是用于xmlns
别名命名空间URI)
在许多情况下,读取器只检查在数据的其命名空间(或默认/空白命名空间) - 。在自定义命名空间值通常跳过
要获得打包原始的XML,一个简单的方法是通过XSLT,只有尊重缺省的/原始的命名空间来运行它。
XNamespace myData = XNamespace.Get("http://mycustomdata/");
XElement el = new XElement("foo",
new XAttribute(XNamespace.Xmlns + "myData", myData.NamespaceName),
new XAttribute("standardAttribute", "abc"),
new XAttribute(myData + "customAttribute", "def"),
new XElement("standardElement", "ghi"),
new XElement(myData + "customAttribute", "jkl"));
string s = el.ToString();
要来自XElement
除去这种数据,也许:
static void Strip(XElement el, XNamespace ns) {
List<XElement> remove = new List<XElement>();
foreach (XElement child in el.Elements()) {
if (child.Name.Namespace == ns) {
remove.Add(child);
} else {
Strip(child, ns);
}
}
remove.ForEach(child => child.Remove());
foreach (XAttribute child in
(from a in el.Attributes()
where a.Name.Namespace == ns
select a).ToList()) {
child.Remove();
}
}
其他提示
在原来的问题所用的词“序列化”,但然后又提到的XElement和注释。对我来说,这是两个不同的东西。
如果你真的想使用XmlSerializer:点击 我会做的是使用XmlAttributeOverrides,区分系列化。 随着XmlAttributeOverrides您可以通过编程,在运行时,将覆盖装饰你的类型的XML序列化的属性。
在你的类型,你可以有旨在保持注释/文档字段/属性。装饰与XmlIgnore。然后,创建一个不接受任何替代XmlSerializer的一个实例。注释不会被序列化或反序列化。该类型创建的XmlSerializer的另一个实例,使用XmlAttributeOverrides对象。上的任何其他成员的指定XmlIgnore'd属性(使用XmlElementAttribute)用于任何属性的覆盖,以及覆盖(利用XmlIgnore =真)。
序列化实例两次,一个与每个串行器。
编辑:这里的代码:
public class DTO
{
[XmlIgnore]
public string additionalInformation;
[XmlElement(Order=1)]
public DateTime stamp;
[XmlElement(Order=2)]
public string name;
[XmlElement(Order=3)]
public double value;
[XmlElement(Order=4)]
public int index;
}
public class OverridesDemo
{
public void Run()
{
DTO dto = new DTO
{
additionalInformation = "This will bbe serialized separately",
stamp = DateTime.UtcNow,
name = "Marley",
value = 72.34,
index = 7
};
// ---------------------------------------------------------------
// 1. serialize normally
// this will allow us to omit the xmlns:xsi namespace
var ns = new XmlSerializerNamespaces();
ns.Add( "", "" );
XmlSerializer s1 = new XmlSerializer(typeof(DTO));
var builder = new System.Text.StringBuilder();
var settings = new XmlWriterSettings { OmitXmlDeclaration = true, Indent= true };
Console.WriteLine("\nSerialize using the in-line attributes: ");
using ( XmlWriter writer = XmlWriter.Create(builder, settings))
{
s1.Serialize(writer, dto, ns);
}
Console.WriteLine("{0}",builder.ToString());
Console.WriteLine("\n");
// ---------------------------------------------------------------
// ---------------------------------------------------------------
// 2. serialize with attribute overrides
// use a non-empty default namespace
ns = new XmlSerializerNamespaces();
string myns = "urn:www.example.org";
ns.Add( "", myns);
XmlAttributeOverrides overrides = new XmlAttributeOverrides();
XmlAttributes attrs = new XmlAttributes();
// override the (implicit) XmlRoot attribute
XmlRootAttribute attr1 = new XmlRootAttribute
{
Namespace = myns,
ElementName = "DTO-Annotations",
};
attrs.XmlRoot = attr1;
overrides.Add(typeof(DTO), attrs);
// "un-ignore" the first property
// define an XmlElement attribute, for a type of "String", with no namespace
var a2 = new XmlElementAttribute(typeof(String)) { ElementName="note", Namespace = myns };
// add that XmlElement attribute to the 2nd bunch of attributes
attrs = new XmlAttributes();
attrs.XmlElements.Add(a2);
attrs.XmlIgnore = false;
// add that bunch of attributes to the container for the type, and
// specifically apply that bunch to the "additionalInformation" property
// on the type.
overrides.Add(typeof(DTO), "additionalInformation", attrs);
// now, XmlIgnore all the other properties
attrs = new XmlAttributes();
attrs.XmlIgnore = true;
overrides.Add(typeof(DTO), "stamp", attrs);
overrides.Add(typeof(DTO), "name", attrs);
overrides.Add(typeof(DTO), "value", attrs);
overrides.Add(typeof(DTO), "index", attrs);
// create a serializer using those xml attribute overrides
XmlSerializer s2 = new XmlSerializer(typeof(DTO), overrides);
Console.WriteLine("\nSerialize using the override attributes: ");
builder.Length = 0;
using ( XmlWriter writer = XmlWriter.Create(builder, settings))
{
s2.Serialize(writer, dto, ns);
}
Console.WriteLine("{0}",builder.ToString());
Console.WriteLine("\n");
// ---------------------------------------------------------------
}
}
输出,使用在线属性:
<DTO>
<stamp>2009-06-30T02:17:35.918Z</stamp>
<name>Marley</name>
<value>72.34</value>
<index>7</index>
</DTO>
输出,使用覆盖属性:
<DTO-Annotations xmlns="urn:www.example.org">
<note>This will bbe serialized separately</note>
</DTO-Annotations>