如何序列化c#中的序列(xs序列,maxOccurs与0不同)

时间:2021-01-01 18:07:00

I'm having an issue to serialize an array in C# to be compliant with a XSD.

我在使用C#序列化数组以符合XSD时遇到问题。

I need to serialize an array, where each property of each child would be listed into one single list, to be compliant with a XSD which define something like this:

我需要序列化一个数组,其中每个子项的每个属性将列在一个列表中,以符合定义如下所示的XSD:

<xs:sequence minOccurs="0" maxOccurs="unbounded">
    <xs:element name="Id" type="xs:string"/>
    <xs:element name="Value" type="xs:string"/>
</xs:sequence>

Exemple, I've got this:

例如,我有这个:

<ServerRequest xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Time>11-08-15 08:27:31</Time>
  <RequestContent>
    <Id>myId1</Id>
    <Value>myValue1</Value>
  </RequestContent>
  <RequestContent>
    <Id>myId2</Id>
    <Value>myValue2</Value>
  </RequestContent>
</ServerRequest>

And what I need is this:

而我需要的是:

<ServerRequest xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Time>11-08-15 08:27:31</Time>
  <Id>myId1</Id>
  <Value>myValue1</Value>
  <Id>myId2</Id>
  <Value>myValue2</Value>
</ServerRequest>

Here is my code sample:

这是我的代码示例:

class Program
{
    static void Main(string[] args)
    {
        ServerRequest test = new ServerRequest();
        test.Time = DateTime.UtcNow.ToString();
        test.RequestContent = new List<ServerRequestContent>()
        {
            new ServerRequestContent() { Id = "myId1", Value = "myValue1"},
            new ServerRequestContent() { Id = "myId2", Value = "myValue2"}
        };

        using (StringWriter sw = new StringWriter())
        {
            XmlSerializer xmlSerializer = new XmlSerializer(typeof(ServerRequest));
            xmlSerializer.Serialize(sw, test);

            Console.WriteLine(sw.ToString());
        }
    }
}


[XmlRoot("ServerRequest")]
public class ServerRequest
{
    [XmlElement()]
    public string Time { get; set; }

    [XmlElement]
    public List<ServerRequestContent> RequestContent { get; set; }
}

public class ServerRequestContent
{
    [XmlElement()]
    public string Id { get; set; }

    [XmlElement()]
    public string Value { get; set; }
}

I've been trying for several hours, but still can't find a solution. Best thing I found so far is this: Serialize Array without root element, but I would have to change a lot of thing in the C# classes generated from the XSD, which I don't really want to.

我已经尝试了几个小时,但仍然无法找到解决方案。到目前为止我发现的最好的事情是:没有根元素的Serialize Array,但是我必须在XSD生成的C#类中改变很多东西,我真的不想这样做。

Thanks for any help

谢谢你的帮助

Solution:

Implementing IXmlSerializable was probably the easiest way to deal with this. ServerRequest class now looks like this:

实现IXmlSerializable可能是解决这个问题的最简单方法。 ServerRequest类现在看起来像这样:

[XmlRoot("ServerRequest")]
public class ServerRequest : IXmlSerializable
{
    [XmlElement()]
    public string Time { get; set; }

    [XmlElement]
    public List<ServerRequestContent> RequestContent { get; set; }

    #region IXmlSerializable

    public XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(XmlReader reader)
    {
        //...
    }

    public void WriteXml(XmlWriter writer)
    {
        writer.WriteElementString("Time", Time);

        foreach (ServerRequestContent content in RequestContent)
        {
            writer.WriteElementString("Id", content.Id);
            writer.WriteElementString("Value", content.Value);
        }
    }

    #endregion
}

1 个解决方案

#1


0  

You should be able to do this by implementing IXmlSerializable on ServerRequest and overriding WriteXml(XmlWriter). See also https://*.com/a/8989781/44853

您应该能够通过在ServerRequest上实现IXmlSerializable并重写WriteXml(XmlWriter)来实现此目的。另请参见https://*.com/a/8989781/44853

Alternatively, while arguably a hack, you could pass the final output through an XSLT transform. For example:

或者,虽然可以说是hack,但您可以通过XSLT转换传递最终输出。例如:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template match="/ServerRequest">
        <ServerRequest xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
                       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <Time><xsl:value-of select="Time"/></Time>
            <xsl:for-each select="RequestContent">
                <Id><xsl:value-of select="Id"/></Id>
                <Value><xsl:value-of select="Value"/></Value>
            </xsl:for-each>
        </ServerRequest>
    </xsl:template>
</xsl:stylesheet>

#1


0  

You should be able to do this by implementing IXmlSerializable on ServerRequest and overriding WriteXml(XmlWriter). See also https://*.com/a/8989781/44853

您应该能够通过在ServerRequest上实现IXmlSerializable并重写WriteXml(XmlWriter)来实现此目的。另请参见https://*.com/a/8989781/44853

Alternatively, while arguably a hack, you could pass the final output through an XSLT transform. For example:

或者,虽然可以说是hack,但您可以通过XSLT转换传递最终输出。例如:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template match="/ServerRequest">
        <ServerRequest xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
                       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <Time><xsl:value-of select="Time"/></Time>
            <xsl:for-each select="RequestContent">
                <Id><xsl:value-of select="Id"/></Id>
                <Value><xsl:value-of select="Value"/></Value>
            </xsl:for-each>
        </ServerRequest>
    </xsl:template>
</xsl:stylesheet>