提问人:Pebermynte Lars 提问时间:11/9/2023 更新时间:11/21/2023 访问量:40
在运行时使用内联 XSD 将 XML 反序列化为 POCO
Deserializing XML into POCO at runtime using inline XSD
问:
作为来自 Azure DevOps 的 REST 响应的一部分,该响应正在反序列化为多个类, JSON 响应的属性之一包含具有内联架构信息的 XML。
架构不是固定的,因为它包含用户生成的列名和值表,表述为 XML。 所以在编译之前,我不知道如何描述我要反序列化的对象。
如何将内联架构转换为运行时生成的对象结构,我的自定义反序列化程序可以使用? 或者这甚至是正确的方法吗?
xml 可能看起来像这样,其中是我的根元素并且始终已知。其余部分取决于用户生成的表。<NewDataSet>
<NewDataSet>
<xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:Locale="">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="Table1">
<xs:complexType>
<xs:sequence>
<xs:element name="status" type="xs:string" minOccurs="0" />
<xs:element name="petId" type="xs:string" minOccurs="0" />
<xs:element name="petName" type="xs:string" minOccurs="0" />
<xs:element name="petStatus" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
<Table1>
<status>available</status>
<petId>0</petId>
<petName>doggie</petName>
<petStatus>available</petStatus>
</Table1>
<Table1>
<status>pending</status>
<petId>1</petId>
<petName>cat</petName>
<petStatus>pending</petStatus>
</Table1>
<Table1>
<status>sold</status>
<petId>2</petId>
<petName>fish</petName>
<petStatus>sold</petStatus>
</Table1>
</NewDataSet>
我的反序列化程序会从根元素的 json 响应中提取 xml,如下所示,就像它对其他已知数据结构所做的那样:
public override NewDataSet? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
// Read XML string and parse it to object of type Steps
var xml = reader.GetString();
var serializer = new XmlSerializer(typeof(NewDataSet));
Log.Debug($"Microsoft.VSTS.TCM.LocalDataSource XML: {xml}");
using var stringReader = new StringReader(xml);
return serializer.Deserialize(stringReader) as NewDataSet;
}
答:
1赞
Alexander Petrov
11/21/2023
#1
DataSet 能够使用内联 XML 架构加载所示格式的 XML。
DataSet dataSet = new DataSet();
dataSet.ReadXml("test.xml");
label.Text = dataSet.Tables[0].TableName;
dataGridView.DataSource = dataSet.Tables[0];
使用数据绑定,它们可以立即显示在网格中。
将架构中的类型更改为,您将无法在网格单元格中输入非数值。petId
xs:int
<xs:element name="petId" type="xs:int" minOccurs="0" />
这可作为使用从 Xml 架构加载的数据类型的证明。DataTable
1赞
Pebermynte Lars
11/21/2023
#2
基于 @alexander-petrov 的答案,我最终采用了这种反序列化方法来处理 XML:
public override DataSet Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
// Read XML string and convert it into a DataSet
var xml = reader.GetString();
using var stringReader = new StringReader(xml);
DataSet dataSet = new DataSet();
dataSet.ReadXml(stringReader, XmlReadMode.ReadSchema);
return dataSet;
}
它将读取内联 XSD,使用我可以迭代的表构建一个数据集,而无需知道 XML 输入的初始大小和形状。
评论