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

时间:2015-08-07 14:55:35

标签: c# xml serialization

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的参数并返回行和列。所以列名都是可变的。我需要做出相当多的不同查询,所以我试图这样做。如果您可以通过各种方式建议更好的解决方案。

2 个答案:

答案 0 :(得分:0)

抱歉,我不相信您使用XmlSerializer标准属性可以提出的要求。您必须使用implementing IXmlSerializable的自定义序列化/反序列化(以下是一些帮助:http://www.codeproject.com/Articles/43237/How-to-Implement-IXmlSerializable-Correctly

您还可以考虑不使用XmlSerializer,而是以更直接的方式使用XML(可能通过LINQ to XMLXmlReader / XmlWriter)。

答案 1 :(得分:0)

使用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);   

            }


        }
    }
}
​