Having issue deserializing string with XSD

十年热恋 提交于 2019-12-23 01:57:04

问题


I'm having trouble trying to deserialise an XML string using an XSD. I'm using c#/Asp.Net along with the DataContractSerializer.

Here's the string as it's returned from a third party:

<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>

Here's the class I'm trying to create:

[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; }
}

It all works fine until I try to validate against my XSD. I'm not an expert here so it's probably something simple.

Incidentally what, I'm trying to achieve, and maybe incorrectly, is to validate against one of the "accepted, "declined" or "rejected" subparts.

<?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>

Here's the message I'm logging:

The element 'ApplicationResponse' has invalid child element 'Id'. List of possible elements expected: 'accepted'.|Stack: 0 - Xml:129;

Any advice appreciated.


回答1:


When you declare the following sequence:

  <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>

that means your expected XML is something like:

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

You should rather try to merge the types in one, as they use the same tags, sometimes optional. For this you have to get rid of the 3 different enumeration simple-types:

<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>

This will validate your input, but it will still allow XML with Status=rejected and an Id pr Price for instance.

In this latest case, you can try to implement another xsd with xs:choice instead of xs:sequence. But I am not sure you can use Status elements with different types.

For quick validation, you can try a free online XML - XSD Validator, as your case is small you can easily do that.

Also, beware in the sequence definition:

  • Price cannot be empty in your XSD
  • Detail simpleType does not match your example (https:// ...)
  • there is no Response type detailed in your XSD


来源:https://stackoverflow.com/questions/34415017/having-issue-deserializing-string-with-xsd

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!