سؤال

لدي موقف حيث لدي ملف XML لا أريد تعديله. توفر وظيفة Addannotation في Class في Xelement خيارا لإضافة بيانات الذاكرة فقط والتي ليست تسلسل وليس جزءا من 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:
ما سأفعله هو استخدام XmlattributeDroides، للتمييز عن التسلسل. مع XMLATTRIBOVEYRIDES يمكنك برمجيا، في وقت التشغيل، تجاوز سمات تسلسل XML التي تزين الأنواع الخاصة بك.

داخل النوع الخاص بك، يمكنك الحصول على حقل / خاصية تهدف إلى الاحتفاظ بالشروح / الوثائق. تزيين ذلك مع xmlignore. بعد ذلك، قم بإنشاء مثيل واحد من Xmlserializer الذي يقبل أي تجاوزات. التعليق التوضيحي لن يكون التسلسل أو التسلسل. قم بإنشاء مثيل آخر من Xmlserializer لهذا النوع، باستخدام كائن XmlattributeLeides. حدد تجاوز خاصية xmlignore'd (استخدم xmlelementattattribute)، بالإضافة إلى تجاوز أي سمات على أي من الأعضاء الآخرين (استخدم xmlignore = true).

تسلسل المثيل مرتين، واحد مع كل تسلسل.


تحرير: إليك الرمز:

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