【问题标题】:How so serialize an element with node name from property value如何从属性值序列化具有节点名称的元素
【发布时间】:2015-10-31 01:55:08
【问题描述】:
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 的参数并返回行和列。所以列名都是可变的。我需要做很多不同的查询,所以我试图这样做。如果您可以提出更好的解决方案,那么无论如何。

【问题讨论】:

  • 与其删除前一个,再问一遍,改进你的另一个问题....stackoverflow.com/questions/31877423/…
  • 是的,好的,点了
  • 如果您使用的是XmlSerializer,我认为您将不得不接受implementing IXmlSerializable(请参阅此处以获得一些帮助:codeproject.com/Articles/43237/…)编辑:您也可以考虑构建更直接的 XML(例如:msdn.microsoft.com/en-us/library/bb387089.aspx
  • 对,你是说因为将属性值映射到元素名称吗?这似乎是有道理的。
  • @MonkeyMan:是的。标准XmlSerializer 在固定模式/结构上效果最好。理想情况下,您的 XML 将具有固定的结构,您只需对其进行序列化/反序列化。这并不总是可能的(尤其是在依赖于第 3 方时),因此您可能已经解决了一些不太理想的问题。

标签: c# xml serialization


【解决方案1】:

抱歉,我不相信您的要求可以使用 XmlSerializer 的标准属性来实现。您将不得不使用implementing IXmlSerializable 的自定义序列化/反序列化(这里有一些帮助:http://www.codeproject.com/Articles/43237/How-to-Implement-IXmlSerializable-Correctly

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2015-09-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-05
      • 1970-01-01
      • 2012-04-14
      • 1970-01-01
      相关资源
      最近更新 更多