XmlSerializer访问父元素中的子逻辑元素

问题描述 投票:1回答:2

我正在使用标准的.NET XmlSerializer反序列化以下xml:

<root>
    <Element>
        <Grouping1>
            <Item1>First</Item1>
            <Item2>Second</Item2>
        </Grouping1>
        <Grouping2>
            <Item3>Third</Item3>
        </Grouping2>
    </Element>
</root>

我想将其序列化为以下类:

class Element
{
    [XmlElement("Item1")]
    public string Item1 { get; set; }

    [XmlElement("Item2")]
    public string Item2 { get; set; }

    [XmlElement("Item3")]
    public string Item3 { get; set; }
}

当然不起作用,因为-例如-<Item1>不在<Element>中,而是在逻辑容器<Grouping1>中。

问题:

是否有一种方法可以告诉XmlSerializerItem1元素中寻找<Grouping1>使[XmlElement("Grouping1.Item1")]的行下降


PS:我不想创建Grouping1类(如建议的here),因为分组只是逻辑容器,不应具有自己的类。

c# xml serialization xml-serialization
2个回答
0
投票

使用Xml Linq。自定义序列化器会复杂得多

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication4
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(FILENAME);

            List<Element> elements = doc.Descendants("Element").Select(x => new Element()
            {
                Item1 = (string)x.Descendants("Item1").FirstOrDefault(),
                Item2 = (string)x.Descendants("Item2").FirstOrDefault(),
                Item3 = (string)x.Descendants("Item3").FirstOrDefault()
            }).ToList();

         }
    }
    class Element
    {
        public string Item1 { get; set; }
        public string Item2 { get; set; }
        public string Item3 { get; set; }
    }


}

这里是序列化器的外观

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;
using System.Xml.Schema;

namespace ConsoleApplication4
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XmlReader reader = XmlReader.Create(FILENAME);
            XmlSerializer serializer = new XmlSerializer(typeof(Root));
            Root root = (Root)serializer.Deserialize(reader);


         }
    }
    [XmlRoot("root")]
    public class Root
    {
        [XmlElement("Element")]
        public List<Element> Element { get; set; }
    }

    public class Element : IXmlSerializable
    {
        private string Item1 { get; set; }
        private string Item2 { get; set; }
        private string Item3 { get; set; }

        public void WriteXml(XmlWriter writer)
        {
            XElement element = new XElement("Element", new object[] {
                new XElement("Grouping1", new object[] {
                    new XElement("Item1", Item1),
                    new XElement("Item2", Item2)
                }),
                new XElement("Grouping2", new XElement("Item3", Item3))
            });
            element.WriteTo(writer);

        }

        public void ReadXml(XmlReader reader)
        {
            XElement element = (XElement)XElement.ReadFrom(reader);

            Item1 = (string)element.Descendants("Item1").FirstOrDefault();
            Item2 = (string)element.Descendants("Item2").FirstOrDefault();
            Item3 = (string)element.Descendants("Item3").FirstOrDefault();

        }

        public XmlSchema GetSchema()
        {
            return (null);
        }
    }


}

0
投票

我不想创建Grouping1类...

不确定在不创建输出该XML的对象的情况下使用序列化是否可行。

串行化的替代方法是使用XmlReader提取所讨论的属性(Item1Item2Item3),并创建Element类型和XmlWriter的列表生成整个XML文件。

假设您的XML文件具有多个Element条目,例如:

<root>
  <Element>
    <Grouping1>
      <Item1>First1</Item1>
      <Item2>Second1</Item2>
    </Grouping1>
    <Grouping2>
      <Item3>Third1</Item3>
    </Grouping2>
  </Element>
  <Element>
    <Grouping1>
      <Item1>First2</Item1>
      <Item2>Second2</Item2>
    </Grouping1>
    <Grouping2>
      <Item3>Third2</Item3>
    </Grouping2>
  </Element>
</root>

...和一个名为Element:]的类

//The serializable attribute is not required here...
public class Element
{
    public Element() { }

    public string Item1 { get; set; }
    public string Item2 { get; set; }
    public string Item3 { get; set; }

    public override string ToString() => $"{Item1}, {Item2}, {Item3}";
}

[创建一个函数来读取文件,创建并返回Element项目的列表:

public List<Element> ReadElements(string xmlFile)
{
    var elements = new List<Element>();
    Element ele = null;

    using (var xr = XmlReader.Create(xmlFile))
        while (xr.Read())
        {
            if (xr.NodeType == XmlNodeType.Element)
            {
                if (xr.Name == "Element")
                    ele = new Element();
                else if (xr.Name == "Item1")
                {
                    xr.Read();
                    ele.Item1 = xr.Value;
                }
                else if (xr.Name == "Item2")
                {
                    xr.Read();
                    ele.Item2 = xr.Value;
                }
                else if (xr.Name == "Item3")
                {
                    xr.Read();
                    ele.Item3 = xr.Value;
                }
            }
            else if (xr.NodeType == XmlNodeType.EndElement)
                if (xr.Name == "Element")
                    elements.Add(ele);
        }
    return elements;
}

...和一种写方法:

public void WriteElements(string xmlFile, IEnumerable<Element> elements)
{
    var xmlSet = new XmlWriterSettings
    {
        Indent = true,
        NewLineOnAttributes = true,
        WriteEndDocumentOnClose = true,
    };

    using (var xr = XmlWriter.Create(xmlFile, xmlSet))
    {
        xr.WriteStartElement("root");                

        foreach(var ele in elements)
        {
            xr.WriteStartElement("Element");
            xr.WriteStartElement("Grouping1");
            xr.WriteStartElement("Item1");
            xr.WriteString(ele.Item1);
            xr.WriteEndElement();
            xr.WriteStartElement("Item2");
            xr.WriteString(ele.Item2);
            xr.WriteEndElement();
            xr.WriteEndElement();
            xr.WriteStartElement("Grouping2");
            xr.WriteStartElement("Item3");
            xr.WriteString(ele.Item3);
            xr.WriteEndElement();
            xr.WriteEndElement();
            xr.WriteEndElement();
        }
    }            
}

读取和写入文件的测试,如:

private void TheCaller()
{
    var xmlFile = "XmlFile.xml";
    var elements = ReadElements(xmlFile);
    elements.ForEach(x => Console.WriteLine(x));
    //...
    WriteElements(xmlFile, elements);
}

在我的输出窗口中打印:

First1, Second1, Third1
First2, Second2, Third2
    
© www.soinside.com 2019 - 2024. All rights reserved.