我有一个情况我有,我不想修改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>
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top