C # не может десериализовать XML, содержащий xsi: type - PullRequest
0 голосов
/ 12 октября 2018

Я пытаюсь десериализовать следующий XML

<?xml version="1.0" encoding="UTF-8"?>
<GovTalkMessage xmlns="http://www.govtalk.gov.uk/CM/envelope">
  <EnvelopeVersion>2.0</EnvelopeVersion>
  <Header>
    <MessageDetails>
      <Class>DRUG_DATA</Class>
      <Qualifier>response</Qualifier>
      <Function>submit</Function>
      <CorrelationID>BD694DAAA26AA6068EAAAE5C7746CE54</CorrelationID>
      <Transformation>XML</Transformation>
    </MessageDetails>
    <SenderDetails>
      <IDAuthentication>
        <SenderID />
        <Authentication>
          <Method />
          <Role />
          <Value />
        </Authentication>
      </IDAuthentication>
    </SenderDetails>
  </Header>
  <GovTalkDetails>
    <Keys>
      <Key Type="SpokeName" />
    </Keys>
  </GovTalkDetails>
  <Body>
    <S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope">
      <S:Body>
        <ns2:getGenericDrugsResponse xmlns:ns2="http://webservice.sirkb/">
          <return>
            <DRUG xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns2:genericDrug">
              <GENERIC_DRUG_ID>147</GENERIC_DRUG_ID>
              <GENERIC_DRUG_NAME>Amoxicilline 125mg/5ml - 60ml</GENERIC_DRUG_NAME>
            </DRUG>
            <DRUG xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns2:genericDrug">
              <GENERIC_DRUG_ID>149</GENERIC_DRUG_ID>
              <GENERIC_DRUG_NAME>Amoxicilline 250mg/5ml - 60ml</GENERIC_DRUG_NAME>
            </DRUG>            
            <DRUG xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns2:genericDrug">
              <DOSAGE>10mg/5ml</DOSAGE>
              <GENERIC_DRUG_ID>2312</GENERIC_DRUG_ID>
              <GENERIC_DRUG_NAME>Vinorelbine (as vinorelbine tartrate)</GENERIC_DRUG_NAME>
              <PHARMACEUTICAL_FORM>concentrate for solution for infusion</PHARMACEUTICAL_FORM>
            </DRUG>
            <DRUG xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns2:genericDrug">
              <DOSAGE>100 u/ml (approximately 0.58mg)</DOSAGE>
              <GENERIC_DRUG_ID>2313</GENERIC_DRUG_ID>
              <GENERIC_DRUG_NAME>Laronidase</GENERIC_DRUG_NAME>
              <PHARMACEUTICAL_FORM>concentrate for solution for infusion</PHARMACEUTICAL_FORM>
            </DRUG>
            <RETURN_STATUS>SUCCESS</RETURN_STATUS>
          </return>
        </ns2:getGenericDrugsResponse>
      </S:Body>
    </S:Envelope>
  </Body>
</GovTalkMessage>

Я сгенерировал классы с помощью Вставить XML как классы в Visual Studio 2017. (Использование xsd.exe - этотоже самое) я не менял сгенерированные классы.

Они имеют следующую форму:

// NOTE: Generated code may require at least .NET Framework 4.5 or .NET Core/Standard 2.0.
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.govtalk.gov.uk/CM/envelope")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.govtalk.gov.uk/CM/envelope", IsNullable = false)]
public partial class GovTalkMessage
{

    private decimal envelopeVersionField;

    private GovTalkMessageHeader headerField;

    private GovTalkMessageGovTalkDetails govTalkDetailsField;

    private GovTalkMessageBody bodyField;

    /// <remarks/>
    public decimal EnvelopeVersion
    {
        get
        {
            return this.envelopeVersionField;
        }
        set
        {
            this.envelopeVersionField = value;
        }
    }

    /// <remarks/>
    public GovTalkMessageHeader Header
    {
        get
        {
            return this.headerField;
        }
        set
        {
            this.headerField = value;
        }
    }

    /// <remarks/>
    public GovTalkMessageGovTalkDetails GovTalkDetails
    {
        get
        {
            return this.govTalkDetailsField;
        }
        set
        {
            this.govTalkDetailsField = value;
        }
    }

    /// <remarks/>
    public GovTalkMessageBody Body
    {
        get
        {
            return this.bodyField;
        }
        set
        {
            this.bodyField = value;
        }
    }
}

/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.govtalk.gov.uk/CM/envelope")]
public partial class GovTalkMessageHeader
{

    private GovTalkMessageHeaderMessageDetails messageDetailsField;

    private GovTalkMessageHeaderSenderDetails senderDetailsField;

    /// <remarks/>
    public GovTalkMessageHeaderMessageDetails MessageDetails
    {
        get
        {
            return this.messageDetailsField;
        }
        set
        {
            this.messageDetailsField = value;
        }
    }

    /// <remarks/>
    public GovTalkMessageHeaderSenderDetails SenderDetails
    {
        get
        {
            return this.senderDetailsField;
        }
        set
        {
            this.senderDetailsField = value;
        }
    }
}

/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.govtalk.gov.uk/CM/envelope")]
public partial class GovTalkMessageHeaderMessageDetails
{

    private string classField;

    private string qualifierField;

    private string functionField;

    private string correlationIDField;

    private string transformationField;

    /// <remarks/>
    public string Class
    {
        get
        {
            return this.classField;
        }
        set
        {
            this.classField = value;
        }
    }

    /// <remarks/>
    public string Qualifier
    {
        get
        {
            return this.qualifierField;
        }
        set
        {
            this.qualifierField = value;
        }
    }

    /// <remarks/>
    public string Function
    {
        get
        {
            return this.functionField;
        }
        set
        {
            this.functionField = value;
        }
    }

    /// <remarks/>
    public string CorrelationID
    {
        get
        {
            return this.correlationIDField;
        }
        set
        {
            this.correlationIDField = value;
        }
    }

    /// <remarks/>
    public string Transformation
    {
        get
        {
            return this.transformationField;
        }
        set
        {
            this.transformationField = value;
        }
    }
}

/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.govtalk.gov.uk/CM/envelope")]
public partial class GovTalkMessageHeaderSenderDetails
{

    private GovTalkMessageHeaderSenderDetailsIDAuthentication iDAuthenticationField;

    /// <remarks/>
    public GovTalkMessageHeaderSenderDetailsIDAuthentication IDAuthentication
    {
        get
        {
            return this.iDAuthenticationField;
        }
        set
        {
            this.iDAuthenticationField = value;
        }
    }
}

/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.govtalk.gov.uk/CM/envelope")]
public partial class GovTalkMessageHeaderSenderDetailsIDAuthentication
{

    private object senderIDField;

    private GovTalkMessageHeaderSenderDetailsIDAuthenticationAuthentication authenticationField;

    /// <remarks/>
    public object SenderID
    {
        get
        {
            return this.senderIDField;
        }
        set
        {
            this.senderIDField = value;
        }
    }

    /// <remarks/>
    public GovTalkMessageHeaderSenderDetailsIDAuthenticationAuthentication Authentication
    {
        get
        {
            return this.authenticationField;
        }
        set
        {
            this.authenticationField = value;
        }
    }
}

/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.govtalk.gov.uk/CM/envelope")]
public partial class GovTalkMessageHeaderSenderDetailsIDAuthenticationAuthentication
{

    private object methodField;

    private object roleField;

    private object valueField;

    /// <remarks/>
    public object Method
    {
        get
        {
            return this.methodField;
        }
        set
        {
            this.methodField = value;
        }
    }

    /// <remarks/>
    public object Role
    {
        get
        {
            return this.roleField;
        }
        set
        {
            this.roleField = value;
        }
    }

    /// <remarks/>
    public object Value
    {
        get
        {
            return this.valueField;
        }
        set
        {
            this.valueField = value;
        }
    }
}

/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.govtalk.gov.uk/CM/envelope")]
public partial class GovTalkMessageGovTalkDetails
{

    private GovTalkMessageGovTalkDetailsKeys keysField;

    /// <remarks/>
    public GovTalkMessageGovTalkDetailsKeys Keys
    {
        get
        {
            return this.keysField;
        }
        set
        {
            this.keysField = value;
        }
    }
}

/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.govtalk.gov.uk/CM/envelope")]
public partial class GovTalkMessageGovTalkDetailsKeys
{

    private GovTalkMessageGovTalkDetailsKeysKey keyField;

    /// <remarks/>
    public GovTalkMessageGovTalkDetailsKeysKey Key
    {
        get
        {
            return this.keyField;
        }
        set
        {
            this.keyField = value;
        }
    }
}

/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.govtalk.gov.uk/CM/envelope")]
public partial class GovTalkMessageGovTalkDetailsKeysKey
{

    private string typeField;

    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public string Type
    {
        get
        {
            return this.typeField;
        }
        set
        {
            this.typeField = value;
        }
    }
}

/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.govtalk.gov.uk/CM/envelope")]
public partial class GovTalkMessageBody
{

    private Envelope envelopeField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Namespace = "http://www.w3.org/2003/05/soap-envelope")]
    public Envelope Envelope
    {
        get
        {
            return this.envelopeField;
        }
        set
        {
            this.envelopeField = value;
        }
    }
}

/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.w3.org/2003/05/soap-envelope")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.w3.org/2003/05/soap-envelope", IsNullable = false)]
public partial class Envelope
{

    private EnvelopeBody bodyField;

    /// <remarks/>
    public EnvelopeBody Body
    {
        get
        {
            return this.bodyField;
        }
        set
        {
            this.bodyField = value;
        }
    }
}

/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.w3.org/2003/05/soap-envelope")]
public partial class EnvelopeBody
{

    private getGenericDrugsResponse getGenericDrugsResponseField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Namespace = "http://webservice.sirkb/")]
    public getGenericDrugsResponse getGenericDrugsResponse
    {
        get
        {
            return this.getGenericDrugsResponseField;
        }
        set
        {
            this.getGenericDrugsResponseField = value;
        }
    }
}

/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://webservice.sirkb/")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://webservice.sirkb/", IsNullable = false)]
public partial class getGenericDrugsResponse
{

    private @return returnField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Namespace = "http://www.govtalk.gov.uk/CM/envelope")]
    public @return @return
    {
        get
        {
            return this.returnField;
        }
        set
        {
            this.returnField = value;
        }
    }
}

/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.govtalk.gov.uk/CM/envelope")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.govtalk.gov.uk/CM/envelope", IsNullable = false)]
public partial class @return
{

    private returnDRUG[] dRUGField;

    private string rETURN_STATUSField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("DRUG")]
    public returnDRUG[] DRUG
    {
        get
        {
            return this.dRUGField;
        }
        set
        {
            this.dRUGField = value;
        }
    }

    /// <remarks/>
    public string RETURN_STATUS
    {
        get
        {
            return this.rETURN_STATUSField;
        }
        set
        {
            this.rETURN_STATUSField = value;
        }
    }
}

/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.govtalk.gov.uk/CM/envelope")]
public partial class returnDRUG
{

    private string dOSAGEField;

    private ushort gENERIC_DRUG_IDField;

    private string gENERIC_DRUG_NAMEField;

    private string pHARMACEUTICAL_FORMField;

    /// <remarks/>
    public string DOSAGE
    {
        get
        {
            return this.dOSAGEField;
        }
        set
        {
            this.dOSAGEField = value;
        }
    }

    /// <remarks/>
    public ushort GENERIC_DRUG_ID
    {
        get
        {
            return this.gENERIC_DRUG_IDField;
        }
        set
        {
            this.gENERIC_DRUG_IDField = value;
        }
    }

    /// <remarks/>
    public string GENERIC_DRUG_NAME
    {
        get
        {
            return this.gENERIC_DRUG_NAMEField;
        }
        set
        {
            this.gENERIC_DRUG_NAMEField = value;
        }
    }

    /// <remarks/>
    public string PHARMACEUTICAL_FORM
    {
        get
        {
            return this.pHARMACEUTICAL_FORMField;
        }
        set
        {
            this.pHARMACEUTICAL_FORMField = value;
        }
    }
}

Я получаю следующую ошибку:

System.InvalidOperationException: 'В документе XML есть ошибка (3314).

Внутреннее исключение

InvalidOperationException: указанный тип не был распознан: name = 'genericDrug', пространство имен = 'http://webservice.sirkb/', в http://www.govtalk.gov.uk/CM/envelope'>.

У меня естьиз этого потока заметил, что если я удалю xsi:type="ns2:genericDrug" из файла XML, я могу десериализовать XML.Я не могу изменить XML, потому что это ответ, который я получаю на запрос.Не рекомендуется делать замену строк в XML, поэтому я ищу лучшее решение.

Это может быть повторяющийся вопрос из этого , но так как я неЯ могу отправить сообщение снова, потому что в разделе комментариев трудно получить помощь.

Исходя из поставленного выше вопроса, я попытался изменить аннотацию public partial class returnDRUG

от

[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.govtalk.gov.uk/CM/envelope")]

до

[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.w3.org/2001/XMLSchema-instance", TypeName = "genericDrug")]

, но все еще не могу проанализировать XML.

Код синтаксического анализа прост

var deserializer = new XmlSerializer(typeof(GovTalkMessage));
TextReader textReader = new StreamReader("drug.xml"); //saved response in file for simplicity
GovTalkMessage response;
response = (GovTalkMessage)deserializer.Deserialize(textReader);
textReader.Close();

Что я могусделать для десериализации XML в объекте GovTalkMessage?

1 Ответ

0 голосов
/ 13 октября 2018

Вам нужно изменить оформление в классе returnDRUG

с этого

[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.govtalk.gov.uk/CM/envelope")]
public partial class returnDRUG

на это

[System.Xml.Serialization.XmlTypeAttribute(TypeName = "genericDrug", Namespace = "http://webservice.sirkb/")]
public partial class returnDRUG

Укажите его тип как «genericDrug», ирешающий бит, исправьте его пространство имен на "http://webservice.sirkb/"

Я только что использовал ваш код и сумел десериализовать с помощью этого изменения.

Объяснение заключается в том, что если вы посмотритев определении DRUG вы можете видеть, что его тип определен как «genericDRUG» в псевдониме пространства имен «ns2»

<DRUG xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns2:genericDrug">

Если вы посмотрите на определение псевдонима ns2, вы увидите, что это «http://webservice.sirkb/"

<ns2:getGenericDrugsResponse xmlns:ns2="http://webservice.sirkb/">

Некоторое дополнение для предотвращения значений по умолчанию для DRUG объектов

Каждое свойство класса returnDrug должно иметь пространство именhttp://www.govtalk.gov.uk/CM/envelope.

Полный класс должен иметь следующую форму:

[System.Xml.Serialization.XmlTypeAttribute(TypeName = "genericDrug", Namespace = "http://webservice.sirkb/")]
public partial class returnDRUG
{

    private string dOSAGEField;

    private ushort gENERIC_DRUG_IDField;

    private string gENERIC_DRUG_NAMEField;

    private string pHARMACEUTICAL_FORMField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Namespace = "http://www.govtalk.gov.uk/CM/envelope")]
    public string DOSAGE
    {
        get
        {
            return this.dOSAGEField;
        }
        set
        {
            this.dOSAGEField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Namespace = "http://www.govtalk.gov.uk/CM/envelope")]
    public ushort GENERIC_DRUG_ID
    {
        get
        {
            return this.gENERIC_DRUG_IDField;
        }
        set
        {
            this.gENERIC_DRUG_IDField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Namespace = "http://www.govtalk.gov.uk/CM/envelope")]
    public string GENERIC_DRUG_NAME
    {
        get
        {
            return this.gENERIC_DRUG_NAMEField;
        }
        set
        {
            this.gENERIC_DRUG_NAMEField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Namespace = "http://www.govtalk.gov.uk/CM/envelope")]
    public string PHARMACEUTICAL_FORM
    {
        get
        {
            return this.pHARMACEUTICAL_FORMField;
        }
        set
        {
            this.pHARMACEUTICAL_FORMField = value;
        }
    }
}
...