如何从属性值序列化具有节点名的元素

本文关键字:节点 元素 从属性 序列化 | 更新日期: 2023-09-27 18:06:48

using System;
using System.IO;
using System.Xml.Serialization;
namespace XmlSerializerExample
{
    internal class Program
    {
        private static void Main()
        {
            var obj = new Rows { Row = new[] { new Row { Columns = new[] { new Column { MaxLength = 5, Name = "ColumnName1", Type = "string", Value = "rah rah rah" } } } } };
            var stream = new MemoryStream();
            var serializer = new XmlSerializer(typeof (Rows));
            serializer.Serialize(stream, obj);
            stream.Position = 0;
            var reader = new StreamReader(stream);
            var str = reader.ReadToEnd();
            Console.WriteLine(str);
            Console.ReadKey(true);
        }
    }
    [XmlType(AnonymousType = true)]
    [XmlRoot(Namespace = "", IsNullable = false, ElementName = "DATASET")]
    public class Rows
    {
        [XmlElement("ROW")]
        public Row[] Row { get; set; }
    }
    [XmlType(AnonymousType = true)]
    public class Row
    {
        [XmlElement]
        public Column[] Columns { get; set; }
    }
    [XmlType(AnonymousType = true)]
    public class Column
    {
        public string Name { get; set; }
        [XmlAttribute(AttributeName = "type")]
        public string Type { get; set; }
        [XmlAttribute(AttributeName = "maxLength")]
        public int MaxLength { get; set; }
        [XmlText]
        public string Value { get; set; }
    }
}

这样序列化:

<?xml version="1.0"?>
<DATASET xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <ROW>
      <Columns type="string" maxLength="5">
      <Name>ColumnName1</Name>rah rah rah</Columns>
  </ROW>
</DATASET>

但我需要它是这样的:

<?xml version="1.0"?>
<DATASET xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <ROW>
      <ColumnName1 type="string" maxLength="5">rah rah rah</ColumnName1>
  </ROW>
</DATASET>

我实际上是在用另一种方式做这件事——我试图将xml反序列化到类中。但是这样更简单——当我掌握了窍门,我就可以反序列化了。

我将调用第三方web服务,它接受类似sql的参数并返回行和列。所以列名都是变量。我需要做一些不同的查询,所以我试图这样做。如果你能提出一个更好的解决方案,那当然可以。

如何从属性值序列化具有节点名的元素

对不起,我不相信你所要求的是可能使用XmlSerializer的标准属性。您必须通过实现IXmlSerializable来使用自定义序列化/反序列化(这里有一些帮助:http://www.codeproject.com/Articles/43237/How-to-Implement-IXmlSerializable-Correctly)

您也可以考虑根本不使用XmlSerializer,而是以更直接的方式处理XML(可能通过LINQ to XML或XmlReader/XmlWriter)。

使用XML Linq。不需要序列化

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string input = 
            "<?xml version='"1.0'"?>" +
            "<DATASET xmlns:xsi='"http://www.w3.org/2001/XMLSchema-instance'" xmlns:xsd='"http://www.w3.org/2001/XMLSchema'">"  +
              "<ROW>" +
                  "<Columns type='"string'" maxLength='"5'">" + 
                  "<Name>ColumnName1</Name>rah rah rah</Columns>" + 
              "</ROW>" +
            "</DATASET>";
            XDocument doc = XDocument.Parse(input);
            foreach (XElement row in doc.Descendants("ROW"))
            {
                // <?xml version="1.0"?>
                //<DATASET xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
                //  <ROW>
                //      <ColumnName1 type="string" maxLength="5">rah rah rah</ColumnName1>
                //  </ROW>
                //</DATASET>
                List<XAttribute> attributes = row.Element("Columns").Attributes().ToList();
                XElement eName = row.Element("Columns").Element("Name");
                string name = eName.Value;
                string value = eName.NextNode.ToString();
                XElement newElement = new XElement(name,value);
                newElement.Add(attributes);
                row.Descendants().Remove();
                row.Add(newElement);   
            }

        }
    }
}
​