Не удалось десериализовать xml из-за пространств имен

У меня есть следующий xml, который я хочу десериализовать в класс C#:

<?xml version = "1.0" encoding = "utf-8"?>
<soap:Envelope xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd = "http://www.w3.org/2001/XMLSchema" xmlns:soapenc = "http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns = "http://www.s1.com/info/" xmlns:types = "http://www.s1.com/info/" xmlns:soap = "http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Header>
    <tns:SessionInfo>
      <SessionId xsi:type = "xsd:string">string</SessionId>
    </tns:SessionInfo>
  </soap:Header>
  <soap:Body soap:encodingStyle = "http://schemas.xmlsoap.org/soap/encoding/">
    <tns:LoginResponse>
      <Result xsi:type = "xsd:boolean">boolean</Result>
    </tns:LoginResponse>
  </soap:Body>
</soap:Envelope>

Я использую следующие классы для десериализации xml:

        public class SessionId
        {

            [XmlAttribute(AttributeName = "type", Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
            public string Type { get; set; }

            [XmlText]
            public string Text { get; set; }
        }

        [XmlRoot(ElementName = "SessionInfo", Namespace = "http://www.s1.com/info/")]
        public class SessionInfo
        {

            [XmlElement(ElementName = "SessionId")]
            public SessionId SessionId { get; set; }

            [XmlAttribute(AttributeName = "id", Namespace = "")]
            public string Id { get; set; }

            [XmlText]
            public string Text { get; set; }
        }

        [XmlRoot(ElementName = "Header", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
        public class Header
        {

            [XmlElement(ElementName = "SessionInfo", Namespace = "http://www.s1.com/info/")]
            public SessionInfo SessionInfo { get; set; }
        }


        [XmlRoot(ElementName = "Result", Namespace = "")]
        public class Result
        {

            [XmlAttribute(AttributeName = "type", Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
            public string Type { get; set; }

            [XmlText]
            public string Text { get; set; }
        }

        [XmlRoot(ElementName = "LoginResponse", Namespace = "http://www.s1.com/info/")]
        public class LoginResponse
        {

            [XmlElement(ElementName = "Result")]
            public Result Result { get; set; }
        }

        [XmlRoot(ElementName = "Body", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
        public class Body
        {

            [XmlElement(ElementName = "LoginResponse", Namespace = "http://www.s1.com/info/")]
            public LoginResponse LoginResponse { get; set; }

            [XmlAttribute(AttributeName = "encodingStyle", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
            public string EncodingStyle { get; set; }

            [XmlText]
            public string Text { get; set; }
        }

        [XmlRoot(ElementName = "Envelope", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
        public class Envelope
        {

            [XmlElement(ElementName = "Header", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
            public Header Header { get; set; }

            [XmlElement(ElementName = "Body", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
            public Body Body { get; set; }

            [XmlAttribute(AttributeName = "xsi", Namespace = "http://www.w3.org/2000/xmlns/")]
            public string Xsi { get; set; }

            [XmlAttribute(AttributeName = "xsd", Namespace = "http://www.w3.org/2000/xmlns/")]
            public string Xsd { get; set; }

            [XmlAttribute(AttributeName = "soapenc", Namespace = "http://www.w3.org/2000/xmlns/")]
            public string Soapenc { get; set; }

            [XmlAttribute(AttributeName = "tns", Namespace = "http://www.w3.org/2000/xmlns/")]
            public string Tns { get; set; }

            [XmlAttribute(AttributeName = "types", Namespace = "http://www.w3.org/2000/xmlns/")]
            public string Types { get; set; }

            [XmlAttribute(AttributeName = "soap", Namespace = "http://www.w3.org/2000/xmlns/")]
            public string Soap { get; set; }

            [XmlText]
            public string Text { get; set; }
        }

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

Мы очень ценим любое понимание проблемы. Спасибо!

Добавьте пространство имен: [XmlElement (ElementName = "SessionId", Namespace = "s1.com/info/ ")]

jdweng 06.04.2021 12:33

@jdweng Я пробовал, но похоже, что это не помогает.

Konstantinos Mavrogiannis 06.04.2021 13:32

Сделайте SessionId строкой: [XmlElement (ElementName = "SessionId", Namespace = "")] общедоступная строка SessionId {get; набор; }

jdweng 06.04.2021 14:01
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
29
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Во-первых, SessionId имеет неправильное пространство имен. Он наследует это от родителя, вам нужно явно указать, что у него его нет, установив для него пустую строку.

Во-вторых, xsi:type имеет особое значение, вам не следует пытаться десериализовать его. Он используется для указания типа содержимого элемента - в данном случае string - и будет использоваться сериализатором. Подразумевается, что это один из многих приемлемых типов. Самый простой способ определить это - использовать object.

Собирая их вместе, это должно сработать:

[XmlElement(ElementName = "SessionId", Namespace = "")]
public object SessionId { get; set; }

SessionId должен содержать объект string со значением string.

Также отмечу и другие мелочи:

  • Вы не должны указывать все привязки пространства имен (например, Xsd) как часть модели. Это более низкий уровень, чем у этой модели, и он будет обрабатываться сериализатором.
  • Вам нужен только XmlRoot в корне
  • Свойства XmlText там, где нет текста, не нужны.
  • Для десериализации Result необходимо внести изменения, аналогичные приведенным выше.
  • ElementName и AttributeName по умолчанию будут использовать имя свойства, поэтому вам не нужно указывать их, если это то, что вы хотите.

Учитывая это, эта модель должна работать:

public class SessionInfo
{
    [XmlElement(Namespace = "")]
    public object SessionId { get; set; }
}

public class Header
{
    [XmlElement(Namespace = "http://www.s1.com/info/")]
    public SessionInfo SessionInfo { get; set; }
}

public class LoginResponse
{
    [XmlElement(Namespace = "")]
    public object Result { get; set; }
}

public class Body
{
    [XmlElement(Namespace = "http://www.s1.com/info/")]
    public LoginResponse LoginResponse { get; set; }

    [XmlAttribute("encodingStyle", Namespace = "http://schemas.xmlsoap.org/soap/envelope/", Form = XmlSchemaForm.Qualified)]
    public string EncodingStyle { get; set; }
}

[XmlRoot(Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public class Envelope
{
    [XmlElement]
    public Header Header { get; set; }

    [XmlElement]
    public Body Body { get; set; }
}

Вы можете увидеть рабочую демонстрацию здесь. Я внес одно изменение в исходный XML - я изменил значение Result с boolean на true, иначе вы получите исключение, потому что boolean не является допустимым значением для этого типа.

Большое спасибо не только за рабочий ответ, но и за объяснение, я все еще учусь, так что это было чрезвычайно полезно для меня!

Konstantinos Mavrogiannis 07.04.2021 11:24

Другие вопросы по теме