如何在 c# 中序列化一个序列(xs 序列,maxOccurs 不同于 0)
How to serialize a sequence in c# (xs sequence with maxOccurs different that 0)
我在使用 C# 序列化数组以符合 XSD 时遇到问题。
我需要序列化一个数组,其中每个 child 的每个 属性 都将列在一个列表中,以符合定义如下的 XSD:
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="Id" type="xs:string"/>
<xs:element name="Value" type="xs:string"/>
</xs:sequence>
例如,我有这个:
<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>
而我需要的是:
<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>
这是我的代码示例:
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; }
}
我已经尝试了几个小时,但仍然找不到解决方案。到目前为止我发现的最好的东西是:Serialize Array without root element,但我必须在从 XSD 生成的 C# classes 中更改很多东西,我真的不想要到.
感谢您的帮助
解法:
实施 IXmlSerializable 可能是处理此问题的最简单方法。 ServerRequest class 现在看起来像这样:
[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
}
您应该能够通过在 ServerRequest
上实施 IXmlSerializable
并覆盖 WriteXml(XmlWriter)
来实现此目的。另见
或者,虽然可以说是 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>
我在使用 C# 序列化数组以符合 XSD 时遇到问题。
我需要序列化一个数组,其中每个 child 的每个 属性 都将列在一个列表中,以符合定义如下的 XSD:
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="Id" type="xs:string"/>
<xs:element name="Value" type="xs:string"/>
</xs:sequence>
例如,我有这个:
<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>
而我需要的是:
<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>
这是我的代码示例:
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; }
}
我已经尝试了几个小时,但仍然找不到解决方案。到目前为止我发现的最好的东西是:Serialize Array without root element,但我必须在从 XSD 生成的 C# classes 中更改很多东西,我真的不想要到.
感谢您的帮助
解法:
实施 IXmlSerializable 可能是处理此问题的最简单方法。 ServerRequest class 现在看起来像这样:
[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
}
您应该能够通过在 ServerRequest
上实施 IXmlSerializable
并覆盖 WriteXml(XmlWriter)
来实现此目的。另见
或者,虽然可以说是 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>