XmlSerializer 平展列表

本文关键字:列表 XmlSerializer | 更新日期: 2023-09-27 18:35:37

我在类的默认实现中遇到了一个不幸的问题。我尝试序列化的结构看起来有点像这样:

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 来实现这一点?

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

XmlSerializer 平展列表

序列化 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>