RestSharp десериализует глубоко вложенный XML-документ

Я изо всех сил пытался заставить RestSharp анализировать следующие возвращенные данные XML:

<?xml version="1.0" encoding="UTF-8"?>
<TICKETANYWHERE>
   <COUPON VER="1.0">
      <RESPONSE>
         <TEMPLATELIST>
            <TEMPLATE ID="000000001">
               <NAME>Some name</NAME>
            </TEMPLATE>
            <TEMPLATE ID="000000001">
               <NAME>Some other name</NAME>
            </TEMPLATE>
         </TEMPLATELIST>
      </RESPONSE>
   </COUPON>
</TICKETANYWHERE>

Он возвращается из API, поэтому у меня нет возможности изменить этот XML. Я создал следующие классы для моделирования файла XML:

public class Template
{
    public string Id { get; set; }

    public string Name { get; set; }
}
public class TemplateList : List<Template>
{}

public class Response
{
    public TemplateList Templates { get; set; }
}
public class Coupon
{
    public decimal Ver { get; set; }

    public Response Response { get; set; }
}
public class TicketAnywhere
{
    public Coupon Coupon { get; set; }
}

Затем я создал следующий модульный тест (вдохновленный)

var d = new XmlDeserializer();
var response = new RestSharp.RestResponse();
var XML = "<TICKETANYWHERE><COUPON VER=\"1.0\"><RESPONSE><TEMPLATELIST><TEMPLATE ID=\"00000001\"><NAME>Some name</NAME></TEMPLATE></TEMPLATELIST></RESPONSE></COUPON></TICKETANYWHERE>";
response.Content = XML;
var r = d.Deserialize<TicketAnywhere>(response);

Однако r.Coupon имеет значение NULL. Что я здесь делаю неправильно?

ОБНОВЛЕНИЕ: я попытался свести проблему к самой простой форме, изменив XML и тест на следующее:

    public class Template
    {
        public string Id { get; set; }
        public string Name { get; set; }
    }

    public class TemplateList
    {
        public List<Template> Templates { get; set; }
    }

    [Test]
    public void AnotherTest()
    {
        var XML = @"<?xml version=""1.0"" encoding=""UTF-8""?>
        <TEMPLATELIST>
            <TEMPLATE ID=""00000001"">
                <NAME>Some name</NAME>
            </TEMPLATE>
            <TEMPLATE ID=""00000002"">
                <NAME>Some name</NAME>
            </TEMPLATE>
        </TEMPLATELIST>";

        var d = new XmlDeserializer();
        var response = new RestSharp.RestResponse();
        response.Content = XML;

        var r = d.Deserialize<TemplateList>(response);
        Assert.That(2, Is.EqualTo(r.Templates.Count));
    }

Который снова терпит неудачу. Однако, если я изменю имя класса с Template => TEMPLATE, все будет работать.


person nover    schedule 27.06.2013    source источник


Ответы (1)


XML чувствителен к регистру в процессе десериализации. Чтобы быстро обойти это, вы можете попробовать

XML = XML.Replace("COUPON", "Coupon");

и т. д. для каждого из имен ваших элементов.

Если вы собираетесь обрабатывать много разных xml-файлов, то стоит найти что-то, что сделает это хорошо для вас.

NB, вы также можете изменить название своей собственности в Template с Coupon на COUPON

person wal    schedule 27.06.2013
comment
Спасибо за разъяснение чувствительности к регистру. Пожалуйста, смотрите мое редактирование вопроса. Поскольку это API возвращает XML, я действительно не в состоянии заменить контент, но, если использование заглавных букв в именах классов решит проблему, я боюсь, что это их путь, даже если это УЖАСНО. Спасибо за помощь!! :) - person nover; 27.06.2013
comment
Есть способ украсить ваши классы С# атрибутами, используя атрибут DeserializeAs, однако у меня это еще не работает, поэтому пока не могу вставить это как альтернативный ответ. - person wal; 27.06.2013
comment
OK. Но на самом деле похоже, что переименование классов и свойств в CAPS работает. Должен ли я опубликовать это как альтернативный ответ, или кредит должен принадлежать вам (вы создаете альтернативный ответ) ?? - person nover; 27.06.2013
comment
хорошо, извините, я переименовал класс, а не свойство. Я добавлю это как ответ. Вам нужно только переименовать имя свойства, а не класс. Таким образом, по крайней мере, ваш код КРИЧИТ на вас немного меньше. - person wal; 27.06.2013
comment
Хм, похоже, что RestSharp использует буквальное имя xml (ШАБЛОН) для разрешения класса. Если у меня нет ни свойства, ни имени класса в CAPS, мой модульный тест не пройден. Думаю, мне просто нужно оставить свой код, кричащий на меня... - person nover; 27.06.2013
comment
Это также относится к свойствам моего класса TEMPLATE, все в заглавных буквах. Неужели RestSharp не выполняет нечеткое сопоставление? - person nover; 27.06.2013
comment
@nover Имя класса в нижнем регистре работает для меня. см. этот дамп изображения: imgur.com/zM0OB8t моя мышь находится над переменной result. показывает Купон определен. И да, вам это понадобится для ВСЕХ свойств, я просмотрел источник restsharp, и у него есть некоторое «соответствие», которое позволяет строчным буквам в xml соответствовать свойствам в ваших именах свойств C #, но не в верхнем регистре. - person wal; 28.06.2013
comment
Интересно, что это работает для вас с именами классов, обычно написанными с заглавной буквы - в любом случае, эта ветка заставила меня двигаться, и теперь у меня есть интеграция API, так что еще раз спасибо за ваши усилия. - person nover; 28.06.2013