【问题标题】:Default xml namespace but not on root using XmlSerializer默认 xml 命名空间,但不在根上使用 XmlSerializer
【发布时间】:2015-04-20 17:19:50
【问题描述】:

所以我正在做的是使用 XmlSerializer 并使用自定义类。其中一个元素还需要一个默认命名空间和它自己的值。但是,默认命名空间必须是动态的。因此,Athens 是该位置元素的命名空间。下一个位置元素可能是伦敦。例如:

<items>
    <item>
         <location xmlns="Athens">True</location>
         <location xmlns="London">False</location>
    </item>
<items>

我曾尝试使用 XmlSerializerNamespaces,但这不允许我为第一个参数使用空字符串。我看到的所有例子都是针对根元素的。我希望它适用于以下课程设置。

[XmlRoot("item")]
public class Item
{
     [XmlElement("location")]
     public string Location { get;set; }
}

【问题讨论】:

    标签: c# xml xmlserializer


    【解决方案1】:

    您可以在您的类中嵌入一个XElement-valued 属性,该属性根据需要使用必要的命名空间和值填充,然后使用XmlAnyElementAttribute 属性对其进行装饰,以告诉XmlSerializer 将其按原样包含在最终的 XML:

    [XmlRoot("item" /*, Namespace = "" */)] // Applies when an Item is the document root.
    [XmlType("item" /*, Namespace = "" */)] // Applies when an Item is not the document root.
    public class Item
    {
        [XmlIgnore]
        public string Location { get; set; }
    
        [XmlIgnore]
        public string LocationNamespace { get; set; }
    
        [XmlAnyElement]
        public XElement LocationElement
        {
            get
            {
                var ns = (XNamespace)LocationNamespace;
                var element = new XElement(ns + "location", Location);
                return element;
            }
            set
            {
                if (value == null)
                {
                    LocationNamespace = Location = null;
                }
                else
                {
                    LocationNamespace = value.Name.Namespace.NamespaceName;
                    Location = value.Value;
                }
            }
        }
    }
    

    当放置(例如)在数组中时,以下类:

    var items = new List<Item> { new Item { Location = true.ToString(), LocationNamespace = "Athens" } };
    

    将被序列化为以下 XML:

    <ArrayOfItem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <item>
            <location xmlns="Athens">True</location>
        </item>
    </ArrayOfItem>
    

    更新

    您更新后的问题需要在每个 Item 中包含一组位置。您可以通过让您的 XmlAnyElement 返回一个 XElements 数组来做到这一点:

    public class Item
    {
        public Item()
        {
            this.Locations = new List<string>();
        }
    
        [XmlIgnore]
        public List<string> Locations { get; set; }
    
        [XmlIgnore]
        public string Location { get; set; }
    
        [XmlAnyElement]
        public XElement [] LocationElements {
            get
            {
                var elements = Locations.Select(l => new XElement(XName.Get("location", l), (l == Location).ToString())).ToArray();
                return elements;
            }
            set
            {
                Locations = value.Select(el => el.Name.Namespace.NamespaceName).ToList();
                Location = value.Where(el => bool.Parse(el.Value)).Select(el => el.Name.Namespace.NamespaceName).Distinct().SingleOrDefault() ?? string.Empty;
            }
        }
    }
    

    然后是下面

            var cities = new List<string> { "Athens", "London", "Salt Lake City" };
            var items = new List<Item> { new Item { Locations = cities, Location = cities[0] }, new Item { Locations = cities, Location = cities[1] } };
    

    生成以下 XML:

    <ArrayOfItem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <item>
            <location xmlns="Athens">True</location>
            <location xmlns="London">False</location>
            <location xmlns="Salt Lake City">False</location>
        </item>
        <item>
            <location xmlns="Athens">False</location>
            <location xmlns="London">True</location>
            <location xmlns="Salt Lake City">False</location>
        </item>
    </ArrayOfItem>
    

    【讨论】:

    • 非常抱歉忘记提及命名空间不会是一个常数。我遍历一个位置列表,每个位置都必须动态设置。
    【解决方案2】:

    你也可以为元素指定一个命名空间,试试这个

    [XmlRoot("item")] public class Item { [XmlElement(ElementName = "location", Namespace="Athens")] public string Location { get;set; } }

    【讨论】:

    • 非常抱歉忘记提及命名空间不会是一个常数。我遍历一个位置列表,每个位置都必须动态设置。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-14
    • 1970-01-01
    相关资源
    最近更新 更多