XML 反序列化会丢失数组项

本文关键字:数组 反序列化 XML | 更新日期: 2023-09-27 18:35:09

我必须反序列化一个 xml...这是我做的一步。

  1. 我用xsd xxx.xml从 xml 生成 XSD ;
  2. 将生成两个 XSD。因此,我使用 xsd x1.xsd x2.xsd /classes 生成 c# 类
  3. 生成一个.cs文件,其中包含所有必需的类。我检查文件。一切似乎都还好。我有一个数组,我可以有 1 个以上的结果。
  4. 在我的代码中,我有一个 xml 要反序列化(我用来生成 xsd 的那个),我用以下代码反序列化它:

    public static T Deserialize(Stream xml)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(T));
        T objectDeserialized = null;
        using (StreamReader reader = new StreamReader(xml))
        {
            objectDeserialized = serializer.Deserialize(reader) as T;
        }
        return objectDeserialized;
    }
    

我得到的是一个只有一个元素的数组,但 xml 有两个元素(我已经在调试时检查过)。可能是什么问题?

更新

遵循 XML 和 XSD...

.XML:

<?xml version="1.0" encoding="UTF-8"?>
    <SELECT_CONFIGURATIONResponse xmlns="http://schemas.microsoft.com/Sql/2008/05/TypedProcedures/dbo">
    <StoredProcedureResultSet0>
        <StoredProcedureResultSet0 xmlns="http://schemas.microsoft.com/Sql/2008/05/ProceduresResultSets/dbo/SELECT_CONFIGURATION">
            <FlowId>653de913-a648-419f-85be-0e7ec93c2892</FlowId>
            <DestinationPath>C:'temp'IncomingFiles2</DestinationPath>
            <OriginPath>xxx</OriginPath>
            <DeleteAfterOperation>true</DeleteAfterOperation>
            <IntervalWatchFolder>150000000</IntervalWatchFolder>
            <SearchPattern>*.*</SearchPattern>
            <Recoverable>true</Recoverable>
            <FlowTypeId>1</FlowTypeId>
            <GatewayId>6be02fcc-ea98-4711-ab08-616a8e7be26a</GatewayId>
            <ServerAddress>sftp://127.0.0.1</ServerAddress>
            <PortNumber>22</PortNumber>
            <RetryCount>10</RetryCount>
            <Protocol_Id>1</Protocol_Id>
            <RequireAuthentication>true</RequireAuthentication>
            <RetryInterval>150000000</RetryInterval>
            <IntervalFileToRecover>150000000</IntervalFileToRecover>
            <ConfigurationId>544effad-d23c-404b-afe0-8c3c50d2fc50</ConfigurationId>
            <ServiceId>70472a23-404b-44d2-a191-d9650cdde3d6</ServiceId>
         </StoredProcedureResultSet0>
         <StoredProcedureResultSet0 xmlns="http://schemas.microsoft.com/Sql/2008/05/ProceduresResultSets/dbo/SELECT_CONFIGURATION">
            <FlowId>73a39040-f4b2-470a-bfd2-cd09f6e91812</FlowId>
            <DestinationPath>C:'temp'IncomingFiles</DestinationPath>
            <OriginPath>Temp2</OriginPath>
            <DeleteAfterOperation>true</DeleteAfterOperation>
            <IntervalWatchFolder>150000000</IntervalWatchFolder>
            <SearchPattern>*.*</SearchPattern>
            <Recoverable>false</Recoverable>
            <FlowTypeId>1</FlowTypeId>
            <GatewayId>b6172429-8056-41cd-9db6-e0a403ba792a</GatewayId>
            <ServerAddress>ftp://127.0.0.1</ServerAddress>
            <PortNumber>21</PortNumber>
            <RetryCount>5</RetryCount>
            <Protocol_Id>2</Protocol_Id>
            <RequireAuthentication>false</RequireAuthentication>
            <RetryInterval>150000000</RetryInterval>
            <IntervalFileToRecover>150000000</IntervalFileToRecover>
            <ConfigurationId>544effad-d23c-404b-afe0-8c3c50d2fc50</ConfigurationId>
            <ServiceId>70472a23-404b-44d2-a191-d9650cdde3d6</ServiceId>
         </StoredProcedureResultSet0>
      </StoredProcedureResultSet0>
      <ReturnValue>0</ReturnValue>
</SELECT_CONFIGURATIONResponse>

XSD 1:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="NewDataSet" targetNamespace="http://schemas.microsoft.com/Sql/2008/05/TypedProcedures/dbo" xmlns:mstns="http://schemas.microsoft.com/Sql/2008/05/TypedProcedures/dbo" xmlns="http://schemas.microsoft.com/Sql/2008/05/TypedProcedures/dbo" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" attributeFormDefault="qualified" elementFormDefault="qualified" xmlns:app1="http://schemas.microsoft.com/Sql/2008/05/ProceduresResultSets/dbo/SELECT_CONFIGURATION">
  <xs:import namespace="http://schemas.microsoft.com/Sql/2008/05/ProceduresResultSets/dbo/SELECT_CONFIGURATION" schemaLocation="xxx_app1.xsd" />
  <xs:element name="SELECT_CONFIGURATIONResponse">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="ReturnValue" type="xs:string" minOccurs="0" />
        <xs:element name="StoredProcedureResultSet0" minOccurs="0" maxOccurs="unbounded">
          <xs:complexType>
            <xs:sequence>
              <xs:element ref="app1:StoredProcedureResultSet0" />
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
    <xs:complexType>
      <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:element ref="SELECT_CONFIGURATIONResponse" />
      </xs:choice>
    </xs:complexType>
  </xs:element>
</xs:schema>

XSD 2:

<?xml version="1.0" standalone="yes"?>
<xs:schema targetNamespace="http://schemas.microsoft.com/Sql/2008/05/ProceduresResultSets/dbo/SELECT_CONFIGURATION" xmlns:mstns="http://schemas.microsoft.com/Sql/2008/05/TypedProcedures/dbo" xmlns="http://schemas.microsoft.com/Sql/2008/05/ProceduresResultSets/dbo/SELECT_CONFIGURATION" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" attributeFormDefault="qualified" elementFormDefault="qualified" xmlns:app1="http://schemas.microsoft.com/Sql/2008/05/ProceduresResultSets/dbo/SELECT_CONFIGURATION">
  <xs:import namespace="http://schemas.microsoft.com/Sql/2008/05/TypedProcedures/dbo" schemaLocation="xxx.xsd" />
  <xs:element name="StoredProcedureResultSet0">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="FlowId" type="xs:string" minOccurs="0" />
        <xs:element name="DestinationPath" type="xs:string" minOccurs="0" />
        <xs:element name="OriginPath" type="xs:string" minOccurs="0" />
        <xs:element name="DeleteAfterOperation" type="xs:string" minOccurs="0" />
        <xs:element name="IntervalWatchFolder" type="xs:string" minOccurs="0" />
        <xs:element name="SearchPattern" type="xs:string" minOccurs="0" />
        <xs:element name="Recoverable" type="xs:string" minOccurs="0" />
        <xs:element name="FlowTypeId" type="xs:string" minOccurs="0" />
        <xs:element name="GatewayId" type="xs:string" minOccurs="0" />
        <xs:element name="ServerAddress" type="xs:string" minOccurs="0" />
        <xs:element name="PortNumber" type="xs:string" minOccurs="0" />
        <xs:element name="RetryCount" type="xs:string" minOccurs="0" />
        <xs:element name="Protocol_Id" type="xs:string" minOccurs="0" />
        <xs:element name="RequireAuthentication" type="xs:string" minOccurs="0" />
        <xs:element name="RetryInterval" type="xs:string" minOccurs="0" />
        <xs:element name="IntervalFileToRecover" type="xs:string" minOccurs="0" />
        <xs:element name="ConfigurationId" type="xs:string" minOccurs="0" />
        <xs:element name="ServiceId" type="xs:string" minOccurs="0" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

生成的类具有以下代码:

...
[System.Xml.Serialization.XmlElementAttribute("StoredProcedureResultSet0")]
public SELECT_CONFIGURATIONResponseStoredProcedureResultSet0[] StoredProcedureResultSet0
{
    get
    {
        return this.storedProcedureResultSet0Field;
    }
    set
    {
       this.storedProcedureResultSet0Field = value;
    }
}
...

XML 反序列化会丢失数组项

好吧,XML 不会针对发布的架构进行验证:

错误: 命名空间中的元素"存储过程结果集0"http://schemas.microsoft.com/Sql/2008/05/TypedProcedures/dbo"具有无效的子元素命名空间中的"StoredProcedureResultSet0"http://schemas.microsoft.com/Sql/2008/05/ProceduresResultSets/dbo/SELECT_CONFIGURATION"。
错误:命名空间中的元素"SELECT_CONFIGURATIONResponse"http://schemas.microsoft.com/Sql/2008/05/TypedProcedures/dbo"具有无效的子元素"返回值"在命名空间"http://schemas.microsoft.com/Sql/2008/05/TypedProcedures/dbo"中。可能元素列表预期:"存储过程结果集0"在命名空间中"http://schemas.microsoft.com/Sql/2008/05/TypedProcedures/dbo"。

因此,您的 XML 或 XSD 需要更改。我会适当地更改first.xsd

<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="NewDataSet" targetNamespace="http://schemas.microsoft.com/Sql/2008/05/TypedProcedures/dbo" xmlns:mstns="http://schemas.microsoft.com/Sql/2008/05/TypedProcedures/dbo" xmlns="http://schemas.microsoft.com/Sql/2008/05/TypedProcedures/dbo" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" attributeFormDefault="qualified" elementFormDefault="qualified" xmlns:app1="http://schemas.microsoft.com/Sql/2008/05/ProceduresResultSets/dbo/SELECT_CONFIGURATION">
  <xs:import namespace="http://schemas.microsoft.com/Sql/2008/05/ProceduresResultSets/dbo/SELECT_CONFIGURATION" schemaLocation="xxx_app1.xsd" />
  <xs:element name="SELECT_CONFIGURATIONResponse">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="StoredProcedureResultSet0">
          <xs:complexType>
            <xs:sequence>
              <xs:element ref="app1:StoredProcedureResultSet0" minOccurs="0" maxOccurs="unbounded" />
            </xs:sequence>
          </xs:complexType>
        </xs:element>
        <xs:element name="ReturnValue" type="xs:string" minOccurs="0" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
    <xs:complexType>
      <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:element ref="SELECT_CONFIGURATIONResponse" />
      </xs:choice>
    </xs:complexType>
  </xs:element>
</xs:schema>

重新生成 xsd 类并对代码进行细微更改(集合在层次结构中向上移动),您就可以开始了。

问题是您的 XML 与您的 XSD 不匹配。 XSD 定义以下层次结构:

public partial class SELECT_CONFIGURATIONResponse
{
     public string ReturnValue { get; set; }
     public SELECT_CONFIGURATIONResponseStoredProcedureResultSet0[] StoredProcedureResultSet0 { get; set; }
}
public partial class SELECT_CONFIGURATIONResponseStoredProcedureResultSet0
{
    public StoredProcedureResultSet0 StoredProcedureResultSet0 { get; set }
}
public partial class StoredProcedureResultSet0
{
    public string FlowId { get; set; }
    // Etc etc
}

即,数组是类CONFIGURATIONResponse的属性,使用方式如下:

        var data = xml.LoadFromXML<SELECT_CONFIGURATIONResponse>();
        for (int i = 0; i < data.StoredProcedureResultSet0.Length; i++)
            Debug.WriteLine(data.StoredProcedureResultSet0[i].StoredProcedureResultSet0.FlowId);

但是,您的 XML 在 INNER 嵌套元素上具有数组,就好像类是这样定义的:

public partial class SELECT_CONFIGURATIONResponse
{
     public string ReturnValue { get; set; }
     public SELECT_CONFIGURATIONResponseStoredProcedureResultSet0 StoredProcedureResultSet0 { get; set; }
}
public partial class SELECT_CONFIGURATIONResponseStoredProcedureResultSet0
{
    public StoredProcedureResultSet0 StoredProcedureResultSet0[] { get; set }
}
public partial class StoredProcedureResultSet0
{
    public string FlowId { get; set; }
    // Etc etc
}

若要修复 XML,需要使其与 XSD 匹配,如下所示:

<?xml version="1.0" encoding="UTF-8"?>
    <SELECT_CONFIGURATIONResponse xmlns="http://schemas.microsoft.com/Sql/2008/05/TypedProcedures/dbo">
    <StoredProcedureResultSet0>
        <StoredProcedureResultSet0 xmlns="http://schemas.microsoft.com/Sql/2008/05/ProceduresResultSets/dbo/SELECT_CONFIGURATION">
            <FlowId>653de913-a648-419f-85be-0e7ec93c2892</FlowId>
            <DestinationPath>C:'temp'IncomingFiles2</DestinationPath>
            <OriginPath>xxx</OriginPath>
            <DeleteAfterOperation>true</DeleteAfterOperation>
            <IntervalWatchFolder>150000000</IntervalWatchFolder>
            <SearchPattern>*.*</SearchPattern>
            <Recoverable>true</Recoverable>
            <FlowTypeId>1</FlowTypeId>
            <GatewayId>6be02fcc-ea98-4711-ab08-616a8e7be26a</GatewayId>
            <ServerAddress>sftp://127.0.0.1</ServerAddress>
            <PortNumber>22</PortNumber>
            <RetryCount>10</RetryCount>
            <Protocol_Id>1</Protocol_Id>
            <RequireAuthentication>true</RequireAuthentication>
            <RetryInterval>150000000</RetryInterval>
            <IntervalFileToRecover>150000000</IntervalFileToRecover>
            <ConfigurationId>544effad-d23c-404b-afe0-8c3c50d2fc50</ConfigurationId>
            <ServiceId>70472a23-404b-44d2-a191-d9650cdde3d6</ServiceId>
         </StoredProcedureResultSet0>
     </StoredProcedureResultSet0>
     <StoredProcedureResultSet0>
         <StoredProcedureResultSet0 xmlns="http://schemas.microsoft.com/Sql/2008/05/ProceduresResultSets/dbo/SELECT_CONFIGURATION">
            <FlowId>73a39040-f4b2-470a-bfd2-cd09f6e91812</FlowId>
            <DestinationPath>C:'temp'IncomingFiles</DestinationPath>
            <OriginPath>Temp2</OriginPath>
            <DeleteAfterOperation>true</DeleteAfterOperation>
            <IntervalWatchFolder>150000000</IntervalWatchFolder>
            <SearchPattern>*.*</SearchPattern>
            <Recoverable>false</Recoverable>
            <FlowTypeId>1</FlowTypeId>
            <GatewayId>b6172429-8056-41cd-9db6-e0a403ba792a</GatewayId>
            <ServerAddress>ftp://127.0.0.1</ServerAddress>
            <PortNumber>21</PortNumber>
            <RetryCount>5</RetryCount>
            <Protocol_Id>2</Protocol_Id>
            <RequireAuthentication>false</RequireAuthentication>
            <RetryInterval>150000000</RetryInterval>
            <IntervalFileToRecover>150000000</IntervalFileToRecover>
            <ConfigurationId>544effad-d23c-404b-afe0-8c3c50d2fc50</ConfigurationId>
            <ServiceId>70472a23-404b-44d2-a191-d9650cdde3d6</ServiceId>
         </StoredProcedureResultSet0>
      </StoredProcedureResultSet0>
      <ReturnValue>0</ReturnValue>
</SELECT_CONFIGURATIONResponse>