XmlSerializer压平List

时间:2014-12-29 10:59:38

标签: c# xml-serialization

我对Class的默认实现有一个不幸的问题。 我正在尝试序列化的结构看起来有点像这样:

public class Request
{
    public Point[] Points { get; set; }
}
public class Point
{
    public int X { get; set; }
    public int Y { get; set; }
}

问题是我尝试发送此文件的服务需要这样的结构

<Request>
    <X1>1.0</X1>
    <Y1>1.0</Y1>
    ...
    <Xn>2.0</Xn>
    <Yn>2.0</Yn>
</Request>

虽然我知道我可以展平数组以将其属性序列化为属性,但我无法找到匹配我所需格式的方法。

有什么办法可以用默认的XmlSerializer实现这个目的吗?

似乎我必须手动实现IXmlSerializable。如果是这样,有没有办法可以自定义此特定List的行为,而无需手动实现整个序列化和反序列化?

1 个答案:

答案 0 :(得分:0)

一旦序列化了Request类,您就可以使用XSLT转换作为中间步骤来获得您想要做的事情。

让我们假设初始XML如下所示

    <Request>
    <Points>
    <Point>
    <X>5</X>
    <Y>6</Y>
    </Point>
    <Point>
    <X>7</X>
    <Y>8</Y>
    </Point>
    <Point>
    <X>9</X>
    <Y>10</Y>
    </Point>
    </Points>
    </Request>

以下代码显示了如何实现。

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Xml;
    using System.Xml.Linq;
    using System.Xml.Xsl;

    namespace StackOverflow
    {
        class Program
        {
            static void Main(string[] args)
            {
                string xslMarkup = @"<?xml version='1.0'?>
    <xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'>
        <xsl:template match='/'>
    <Request>

       <xsl:for-each select='Request/Points/Point'>

         <xsl:text disable-output-escaping='yes'>&lt;X</xsl:text>
          <xsl:value-of select='position()'/>
           <xsl:text disable-output-escaping='yes'>&gt;</xsl:text>
                <xsl:value-of select='X'/>
          <xsl:text disable-output-escaping='yes'>&lt;/X</xsl:text>
          <xsl:value-of select='position()'/>
           <xsl:text disable-output-escaping='yes'>&gt;</xsl:text>

      <xsl:text disable-output-escaping='yes'>&lt;Y</xsl:text>
          <xsl:value-of select='position()'/>
           <xsl:text disable-output-escaping='yes'>&gt;</xsl:text>
                <xsl:value-of select='Y'/>
          <xsl:text disable-output-escaping='yes'>&lt;/Y</xsl:text>
          <xsl:value-of select='position()'/>
           <xsl:text disable-output-escaping='yes'>&gt;</xsl:text>


       </xsl:for-each>

    </Request>
    </xsl:template>
    </xsl:stylesheet>";

                XDocument xmlTree = new XDocument(
                    new XElement("Request",
                        new XElement("Points",
                            new XElement("Point",
                                new XElement("X", "5"),
                                new XElement("Y", "6")
                                ),
                                 new XElement("Point",
                                    new XElement("X", "7"),
                                    new XElement("Y", "8")
                                    ),
                                     new XElement("Point",
                                        new XElement("X", "9"),
                                        new XElement("Y", "10")
                                        )

                    )
                    )
                );

                XDocument newTree = new XDocument();
                using (XmlWriter writer = newTree.CreateWriter())
                {
                    // Load the style sheet.
                    XslCompiledTransform xslt = new XslCompiledTransform();
                    xslt.Load(XmlReader.Create(new StringReader(xslMarkup)));

                    // Execute the transform and output the results to a writer.
                    xslt.Transform(xmlTree.CreateReader(), writer);
                }



                Console.WriteLine(System.Net.WebUtility.HtmlDecode(newTree.ToString()));
            }
        }
    }

获得的输出如下所示

<Request><X1>5</X1><Y1>6</Y1><X2>7</X2><Y2>8</Y2><X3>9</X3><Y3>10</Y3></Request>