使用XSD反序列化字符串时出现问题

本文关键字:问题 字符串 XSD 反序列化 使用 | 更新日期: 2023-09-27 18:27:52

我在尝试使用XSD取消序列化XML字符串时遇到问题。我正在使用c#/Asp.Net和DataContractSerializer。

这是从第三方返回的字符串:

<ApplicationResponse xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Id>11625807</Id>
    <Status>Declined</Status>
    <Response>1</Response>
    <Price />
    <Detail>No Qualified Buyers Found</Detail>
</ApplicationResponse>

这是我试图创建的类:

[DataContract(Name = "ApplicationResponse", Namespace = "")]
public class SCFResponse
{
    [DataMember]
    public string Id { get; set; }
    [DataMember]
    public string Status { get; set; }
    [DataMember]
    public string Response { get; set; }
    [DataMember]
    public decimal Price { get; set; }
    [DataMember]
    public string Detail { get; set; }
}

在我尝试根据XSD进行验证之前,一切都很好。我不是这里的专家,所以这可能很简单。

顺便说一句,我试图实现的,也许是错误的,是根据"接受"、"拒绝"或"拒绝"的子部分之一进行验证

<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="ApplicationResponse" type="root"/>
  <xs:complexType name="root">
    <xs:sequence>
      <xs:element name="accepted" type="acceptedLead"/>
      <xs:element name="declined" type="declinedLead"/>
      <xs:element name="rejected" type="rejectedLead"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="acceptedLead">
    <xs:sequence>
      <xs:element name="Id" type="id"/>
      <xs:element name="Status" type="acceptedStatus"/>
      <xs:element name="Price" type="price"/>
      <xs:element name="Detail" type="url"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="declinedLead">
    <xs:sequence>
      <xs:element name="Id" type="id"/>
      <xs:element name="Status" type="declinedStatus"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="rejectedLead">
    <xs:sequence>
      <xs:element name="Status" type="rejectedStatus"/>
    </xs:sequence>
  </xs:complexType>
  <xs:simpleType name="acceptedStatus">
    <xs:restriction base="xs:string">
      <xs:enumeration value="Accepted"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="declinedStatus">
    <xs:restriction base="xs:string">
      <xs:enumeration value="Declined"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="rejectedStatus">
    <xs:restriction base="xs:string">
      <xs:enumeration value="Rejected"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="id">
    <xs:restriction base="xs:string">
      <xs:enumeration value="([0-9])+"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="price">
    <xs:restriction base="xs:decimal">
      <xs:minInclusive value="0.00"/>
      <xs:maxInclusive value="100.00"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="url">
    <xs:restriction base="xs:anyURI">
      <xs:pattern value="https://.+" />
    </xs:restriction>
  </xs:simpleType>
</xs:schema>

这是我正在记录的消息:

元素"ApplicationResponse"具有无效的子元素"Id"。需要可能元素的列表:"accepted"|堆栈:0-Xml:129;

如有任何建议,不胜感激。

使用XSD反序列化字符串时出现问题

当您声明以下序列时:

  <xs:complexType name="root">
    <xs:sequence>
      <xs:element name="accepted" type="acceptedLead"/>
      <xs:element name="declined" type="declinedLead"/>
      <xs:element name="rejected" type="rejectedLead"/>
    </xs:sequence>
  </xs:complexType>

这意味着您期望的XML类似于:

<ApplicationResponse ...>
    <accepted>...</accepted>
    <declined>...</declined>
    <rejected>...</rejected>
</ApplicationResponse>

您应该尝试将类型合并为一个,因为它们使用相同的标记,有时是可选的。为此,您必须去掉3种不同的枚举简单类型:

<xs:complexType name="root">
  <xs:element name="Id" type="id" minOccurs="0"/>
  <xs:element name="Status" type="statusEnum"/>
  <xs:element name="Price" type="price" minOccurs="0"/>
  <xs:element name="Detail" type="url" minOccurs="0"/>
</xs:complexType>
...
<xs:simpleType name="statusEnum">
  <xs:restriction base="xs:string">
    <xs:enumeration value="Accepted"/>
    <xs:enumeration value="Declined"/>
    <xs:enumeration value="Rejected"/>
  </xs:restriction>
</xs:simpleType>

这将验证您的输入,但它仍然允许Status=rejected和Id pr Price的XML。

在这个最新的例子中,您可以尝试使用xs:choice而不是xs:sequence来实现另一个xsd。但我不确定是否可以将Status元素与不同类型一起使用。

为了快速验证,您可以尝试一个免费的在线XML-XSD验证器,因为您的情况很小,您可以轻松地做到这一点。

此外,在序列定义中要小心:

  • XSD中的价格不能为空
  • Detail simpleType与您的示例不匹配(https://…)
  • XSD中没有详细的响应类型