문제

수정하고 싶지 않은 XML 파일이있는 상황이 있습니다. 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 네임 스페이스-우리에 대한 별칭)

대부분의 경우 독자는 데이터 만 확인하고 있습니다. 그들의 네임 스페이스 (또는 기본/빈 네임 스페이스) - 사용자 정의 네임 스페이스의 값은 일반적으로 건너 뜁니다.

원래 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();

An에서 그러한 데이터를 제거합니다 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();
        }
    }

다른 팁

원래 질문은 "Serialize"라는 단어를 사용했지만 Xlement와 주석도 언급했습니다. 나에게 이것들은 두 가지 다른 것입니다.

XMLSerializer를 정말로 사용하려면 :
내가 할 일은 xmlattributeoverrides를 사용하여 직렬화를 구별하는 것입니다. XMLATTRIBITEWORRIDES를 사용하면 런타임에 프로그래밍 방식으로 유형을 장식하는 XML 직렬화 속성을 무시할 수 있습니다.

유형 내에서는 주석/문서를 보유하기위한 필드/속성을 가질 수 있습니다. xmlignore로 장식하십시오. 그런 다음 재정의를 수락하지 않는 xmlserializer의 하나의 인스턴스를 만듭니다. 주석은 직렬화되거나 해제되지 않습니다. xmlattributeoverrides 객체를 사용하여 해당 유형에 대해 xmlserializer의 다른 인스턴스를 만듭니다. Xmlignore'd 속성 (xmlelementattribute 사용)에 대한 재정의를 지정하고 다른 멤버의 속성에 대해 재정의합니다 (xmlignore = true aude aked).

인스턴스를 두 번, 각 시리얼 라이저마다 직렬화하십시오.


편집 : 코드는 다음과 같습니다.

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>

Override 속성을 사용하여 출력 :

<DTO-Annotations xmlns="urn:www.example.org">
  <note>This will bbe serialized separately</note>
</DTO-Annotations>
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top