Десериализация XML Unicode

У меня есть файл XML следующим образом:

<?xml version="1.0" encoding="UTF-8"?>
<students xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
     <student name="Adnand"/>
     <student name="özil"/>
     <student name="ärnold"/>
</students>

Как видите, у меня UTF-8 кодировка, но я использовал некоторые символы, отличные от UTF-8 (ö, ä).

Я использую следующий код для десериализации этого XML:

public void readXML(string path)
{
    XmlSerializer deserializer = new XmlSerializer(typeof(Students));
    TextReader reader = new StreamReader(path);       
    object obj = deserializer.Deserialize(reader);
    Students myStudents = (Students)obj;
}

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

ОТВЕТ Вы должны указать Encoding.Default, например

public void readXML(string path)
{
    XmlSerializer deserializer = new XmlSerializer(typeof(Students));
    TextReader reader = new StreamReader(path, Encoding.Default);       
    object obj = deserializer.Deserialize(reader);
    Students myStudents = (Students)obj;
}

person Adnand    schedule 16.05.2018    source источник
comment
Может быть, TextReader reader = new StreamReader(path, Encoding.UTF8); сработает?   -  person Freggar    schedule 16.05.2018
comment
Все еще такой же.   -  person Adnand    schedule 16.05.2018
comment
Пробовал и другие форматы кодирования.   -  person Adnand    schedule 16.05.2018
comment
Нет символов, отличных от UTF-8. UTF-8 позволяет кодировать все символы Unicode.   -  person xanatos    schedule 16.05.2018
comment
Вы также пробовали Encoding.Default? возможно, ваш файл действительно не закодирован как UTF-8   -  person Freggar    schedule 16.05.2018
comment
Да, Encoding.Default выполняет свою работу. Спасибо. Пожалуйста, отредактируйте ответ, чтобы я мог его принять :)   -  person Adnand    schedule 16.05.2018
comment
Как убедиться, что он не работает? Вы смотрели на результаты в отладчике или в окне консоли? Потому что я думаю, что это просто должно было сработать.   -  person bommelding    schedule 16.05.2018
comment
@bommelding ваше решение также может работать, но мне может потребоваться изменить весь код, чтобы реализовать его.   -  person Adnand    schedule 16.05.2018
comment
Извините, я встречаюсь с решением Marco Salernos. Без указания кодировки по умолчанию не работает, не знаю почему. Я просмотрел результаты в отладчике, а также результаты, хранящиеся в моей базе данных.   -  person Adnand    schedule 16.05.2018
comment
ö, ä являются символами UTF8. Эта страница является страницей UTF8, поэтому вы можете видеть эти символы в первую очередь. Ваш фактический файл file хранится как файл UTF8, или это файл ANSI, который просто имеет текст UTF-8 в атрибуте кодирования?   -  person Panagiotis Kanavos    schedule 16.05.2018
comment
@Adnand, кстати, UTF8 работает без дополнительных усилий. Если у вас возникли проблемы, это связано с тем, что файл не использует кодировку UTF-8. Сохраните его снова как UTF8 или конвертируйте.   -  person Panagiotis Kanavos    schedule 16.05.2018
comment
Вам необходимо выяснить, почему фактическая кодировка файла отличается от указанной в декларации. И устранить это несоответствие.   -  person Alexander Petrov    schedule 16.05.2018


Ответы (3)


Кажется, ваш файл закодирован не как UTF-8, а как кодировка Windows по умолчанию ANSI.

Определение StreamReader как

TextReader reader = new StreamReader(path, Encoding.Default)

должен сделать трюк.


Обратите внимание, что это скорее обходной путь, и использование Encoding.Default на самом деле очень плохая идея, поскольку она сломается при использовании другой культуры. Эта статья дает хороший обзор, почему вам не следует использовать Encoding.Default (спасибо Александру за то, что поделился). Лучше использовать UTF-8, так как большинство систем справятся с этим.

В вашем конкретном случае, чтобы фактически сохранить файл как UTF-8, вам необходимо:

  • Адаптируйте программу, создающую файл, для вывода в формате UTF-8.

  • Или, если вы использовали текстовый редактор для создания файла, используйте текстовый редактор, поддерживающий кодировку UTF-8 (например, Notepad++).

person Freggar    schedule 16.05.2018

Вы можете использовать StreamReader для указания кодировки

var Students xmlObject = null;
using (var streamReader = new StreamReader(inXML, Encoding.UTF8, true)) {
    var xmlSerializer = new XmlSerializer(typeof(Students));
    xmlObject = (Students)xmlSerializer.Deserialize(streamReader);
}

Также вы пытались использовать кодировку «ISO-8859-1», я использую ее в основном для иностранных символов.

person Werme    schedule 16.05.2018
comment
Еще ничего. Где указать кодировку ISO-8859-1? - person Adnand; 16.05.2018
comment
Поскольку он не используется по умолчанию, используйте GetEncoding(string) → new StreamReader(inXML, Encoding.GetEncoding(ISO-8859-1), true) - person Werme; 16.05.2018
comment
@Adnand вместо того, чтобы пытаться использовать несколько кодировок, исправьте файл. Если он говорит UTF-8, файл должен быть сохранен как UTF8. - person Panagiotis Kanavos; 16.05.2018
comment
@PanagiotisKanavos должно быть так, как вы говорите, но я просто использую файл, я не создатель. - person Adnand; 16.05.2018
comment
@Adnand Можете ли вы отправить его обратно в отчете об ошибке с предложением использовать библиотеку для написания XML-документов, чтобы она записывала объявление кодировки в соответствии с кодировкой файла? - person Tom Blodget; 17.05.2018

Это работает для меня:

class Program
{
    static void Main(string[] args)
    {
        List<Student> students = new List<Student>();
        XDocument xDocument = XDocument.Load("icsemmelle.xml");
        List<XElement> xStudents = xDocument.Descendants("student").ToList();
        foreach(XElement xStudent in xStudents)
        {
            students.Add(new Student { Name = xStudent.Attribute("name").Value });
        }
    }
}

class Student
{
    public string Name { get; set; }
}
person Marco Salerno    schedule 16.05.2018
comment
Да, у XLinq нет проблем с символами, но для этого требуется ручная десериализация. - person bommelding; 16.05.2018
comment
На самом деле он попросил альтернативы, таким образом большинство возможных проблем уже решено. - person Marco Salerno; 16.05.2018
comment
@MarcoSalerno LINQ не имеет ничего общего с кодировками. Если это работает, это потому, что файл UTF8 и десериализация прошла успешно. - person Panagiotis Kanavos; 16.05.2018
comment
@PanagiotisKanavos, к счастью, ты сказал мне, что раньше это было не очевидно - person Marco Salerno; 16.05.2018
comment
@MarcoSalerno, если это так, то почему этот код вообще не влияет на результат? Если вы попытаетесь использовать этот код с файлом ANSI, вы все равно получите - person Panagiotis Kanavos; 16.05.2018
comment
Потому что проблема заключалась в самом подходе - person Marco Salerno; 16.05.2018
comment
@MarcoSalerno этот ответ не показывает другого подхода. это даже не связано - person Panagiotis Kanavos; 16.05.2018
comment
@MarcoSalerno, почему бы вам сначала не попробовать это с файлом ANSI, который не соответствует локали вашего компьютера? И ищите SO для других вопросов, связанных с символом замены Unicode? Если вы действительно настаиваете, вы можете даже проверьте исходный код и убедитесь, что он не делает ничего особенного. Это просто вызов XmlReader.Create - person Panagiotis Kanavos; 16.05.2018
comment
Учитывая, что файл представляет собой utf-8, мой код точно работает. - person Marco Salerno; 16.05.2018
comment
@MarcoSalerno файл не является UTF8, хотя он имеет это значение в теге encoding. Файл UTF8 – это файл, сохраненный с использованием кодировки UTF8. Вот почему проблема возникла в первую очередь и почему принятый ответ сработал. Вы еще не попробовали свой код с файлом, отличным от Unicode. Попробуй. - person Panagiotis Kanavos; 16.05.2018
comment
Поэтому ОП попросил решение другой проблемы. Он четко заявляет, что кодировка правильная. - person Marco Salerno; 16.05.2018
comment
@MarcoSalerno да, ОП правильный. Вы неправильно понимаете, что означает кодировка. Это не значение тега encoding. Это фактическая кодировка файла, которая связана с тем, какие байты хранятся для каждого символа. Это то, что вы передаете в параметр Encoding чтения файлов, записи, вызовы File.WriteAllText и т. д. - person Panagiotis Kanavos; 16.05.2018
comment
@MarcoSalerno, чтобы попробовать, сохраните текст вопроса с помощью File.WriteAllText(..,...,Encoding.GetEncoding(1251)), а затем попробуйте свой код. Вместо özil вы получите ozil - person Panagiotis Kanavos; 16.05.2018
comment
Я не говорю о значении тега кодирования. - person Marco Salerno; 16.05.2018