使用XSD解决字符串反序列化问题

时间:2015-12-22 11:35:25

标签: c# xml xsd

我在尝试使用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'。预期可能元素列表:'已接受'。| Stack:0 - Xml:129;

任何建议表示赞赏。

1 个答案:

答案 0 :(得分:1)

声明以下序列时:

  <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的XML和例如Id pr Price。

在最新的情况下,您可以尝试使用xs:choice而不是xs:sequence来实现另一个xsd。但我不确定您是否可以使用不同类型的Status元素。

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

另外,请注意序列定义:

  • XSD中的价格不能为空
  • 详细信息simpleType与您的示例(https:// ...)
  • 不符
  • 您的XSD中没有详细说明的响应类型