簡體   English   中英

C#使用XmlText序列化XmlElement

[英]C# Serializing XmlElement with XmlText

我需要復制這種XML格式:

<item>
    <attribute1>1</attribute1>
    <attribute2 something="true">
        2
    </attribute2>
    <attribute3 something="false">
        3
    </attribute3>
    <!-- goes on until attribute25 -->
</item>

我目前正在使用這樣的東西來實現我想要的東西:

Item.cs:

[XmlType(TypeName = "item")]
public class Item {

    [XmlElement("attribute1")]
    public CustomElement<string> Attribute1 { get; set; }

    [XmlElement("attribute2")]
    public CustomElement<string> Attribute2 { get; set; }

    [XmlElement("attribute3")]
    public CustomElement<string> Attribute3 { get; set; }

    // Etc Etc
}

CustomElement.cs:

/// <summary>
///     Represents a CustomElement.
/// </summary>
/// <typeparam name="T">The type for the value of the element.</typeparam>

public class CustomElement<T>
{
    [XmlIgnore] public T Value;

    [XmlText]
    public T XmlValue => Value;

    public CustomElement()
    {
    }

    public CustomElement(T value)
    {
        Value = value;
    }

    [XmlIgnore]
    public bool? Something { get; set; }

    [XmlAttribute("something")]
    public bool XmlSomething
    {
        get => Something != null && Something.Value;
        set => Something = value;
    }

    public bool XmlSomethingSpecified => Something.HasValue;

    public static implicit operator CustomElement<T>(T x)
    {
        return new CustomElement<T>(x);
    }
}

但是,在序列化我的Item我得到:

<item>
    <attribute1 />
    <attribute2 />
    <attribute3 />
</item>

如何修復我的CustomElement類,以便不會丟失值?

你有幾個問題:

  1. 您正在嘗試將XmlValue成員序列化為為CustomElement<T>實例生成的元素的元素值,但您已將其定義為只讀 表達式 - 身體成員

     public T XmlValue => Value; 

    XmlSerializer只會序列化公共讀/寫屬性和字段,因此您必須添加setter和getter:

     [XmlText] public T XmlValue { get => Value; set => Value = value; } 

    或者,為了簡化模型,您可以完全消除XmlValue並通過使用[XmlText]標記來直接序列化Value XML序列化屬性可以應用於字段和屬性。

  2. 您正在嘗試使用{propertyName}Specified模式在基礎值為null時禁止<something>元素的序列化。 此模式主要用於跟蹤是否遇到關聯元素,因此必須使用[XmlIgnore]標記xxxSpecified屬性:

     [XmlIgnore] public bool XmlSomethingSpecified => Something.HasValue; 

    或者,由於您實際上不需要跟蹤<something>元素的存在,您可以通過切換到ShouldSerialize{PropertyName}()模式來簡化模型:

     public bool ShouldSerializeXmlSomething() => Something.HasValue; 

    兩個模式之間的差異在ShouldSerialize ()vs Specified Conditional Serialization Pattern中描述

  3. 如果您的Item類型將是XML文檔的根元素,則必須使用[XmlRoot("item")]標記它以使根元素的名稱為<item>

     [XmlRoot("item")] [XmlType(TypeName = "ci")] public class Item { // Etc Etc } 
  4. 在您的c#代碼中,您已使用[XmlElement]標記了XmlSomething屬性,但在XML中, something內容顯示為元素<something>true</something>

    如果你真的希望它是一個元素,你必須用[XmlElement]標記XmlSomething

     [XmlElement("something")] public bool XmlSomething { get => Something != null && Something.Value; set => Something = value; } 
  5. 在您的問題中,您將顯示具有非布爾文本值的<something>元素的示例:

     <attribute3> 3 <something>text</something> </attribute3> 

    我認為這是問題中的拼寫錯誤,但如果沒有,您將需要重新設計您的CustomElement<T>類型以使Something成為string

樣本工作Roslyn .Net小提琴第二個用於CustomElement<T>的建議簡化, 第三個用 <something>作為子元素出現。

來自第二小提琴的課程如下:

public class CustomElement<T>
{
    [XmlText]
    public T Value;

    public CustomElement()
    {
    }

    public CustomElement(T value)
    {
        Value = value;
    }

    [XmlIgnore]
    public bool? Something { get; set; }

    [XmlAttribute("something")]
    public bool XmlSomething
    {
        get => Something != null && Something.Value;
        set => Something = value;
    }

    public bool ShouldSerializeXmlSomething() => Something.HasValue;

    public static implicit operator CustomElement<T>(T x)
    {
        return new CustomElement<T>(x);
    }
}

[XmlRoot("item")]
[XmlType(TypeName = "ci")]
public class Item
{
    [XmlElement("attribute1")]
    public CustomElement<string> Attribute1 { get; set; }

    [XmlElement("attribute2")]
    public CustomElement<string> Attribute2 { get; set; }

    [XmlElement("attribute3")]
    public CustomElement<string> Attribute3 { get; set; }

    // Etc Etc
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM