Десериализация XML без пространств имен, но в классе, ожидающем пространства имен
Дубликат:
пропуск всех пространств имен xml при сериализации объекта?
Не тот же.. Я хочу по-другому: Десериализоваться!
У меня есть класс C#, как показано ниже:
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.portalfiscal.inf.br/nfe")]
[System.Xml.Serialization.XmlRootAttribute("NFe", Namespace = "http://www.portalfiscal.inf.br/nfe", IsNullable = false)]
public partial class TNFe
{
private TNFeInfNFe infNFeField;
private SignatureType signatureField;
/// <remarks/>
public TNFeInfNFe infNFe
{ ...
Я использую этот класс для сериализации / десериализации XML-файлов по запросу пользователя.
Но у меня есть проблема: определение пространств имен было добавлено в новую версию этого программного обеспечения.
XML остается тем же самым, только добавляя определение пространств имен.
Напр., последний версия...
<?xml version="1.0" encoding="utf-8" ?>
<NFe>
<infNFe version="1.10">
...
И новая версия...
<?xml version="1.0" encoding="utf-8" ?>
<NFe xmlns="http://www.portalfiscal.inf.br/nfe">
<infNFe version="2.10">
...
Мне нужно загрузить XML-файлы с этими пространствами имен и без них.
У меня есть много вложенных классов, и каждый из них имеет свое собственное определение пространств имен.
Я хотел бы использовать одни и те же классы для обоих XML, с пространствами имен и без них.
Я попытался создать XmlTextReader и перезаписать метод NamespaceURI, но по-прежнему получаю исключение без большой информации. Я думаю, что .NET engine пытается заставить класс определение пространства имен по отношению к XML.
4 ответов:
Я столкнулся с подобной проблемой с прокси-классом. По причинам, которые я не буду вдаваться в подробности, мне нужно было сериализовать класс вручную с помощью XmlSerializer на веб-сервере и десериализовать на клиенте. Мне не удалось найти элегантное решение в интернете, поэтому я просто избежал этой проблемы, удалив атрибут XmlTypeAttribute из прокси-класса вручную после его автоматического создания в Visual Studio.
Я все время возвращался, чтобы посмотреть, есть ли способ заставить пространство имен тренироваться. Вот как я его получил Работа без необходимости изменять автоматически генерируемые классы. В итоге я использовал XmlTextReader, чтобы возвращать нужное пространство имен на узлах, соответствующих имени свойства. Есть место для улучшения, но я надеюсь, что это кому-то поможет.
class Program { static void Main(string[] args) { //create list to serialize Person personA = new Person() { Name = "Bob", Age = 10, StartDate = DateTime.Parse("1/1/1960"), Money = 123456m }; List<Person> listA = new List<Person>(); for (int i = 0; i < 10; i++) { listA.Add(personA); } //serialize list to file XmlSerializer serializer = new XmlSerializer(typeof(List<Person>)); XmlTextWriter writer = new XmlTextWriter("Test.xml", Encoding.UTF8); serializer.Serialize(writer, listA); writer.Close(); //deserialize list from file serializer = new XmlSerializer(typeof(List<ProxysNamespace.Person>)); List<ProxysNamespace.Person> listB; using (FileStream file = new FileStream("Test.xml", FileMode.Open)) { //configure proxy reader XmlSoapProxyReader reader = new XmlSoapProxyReader(file); reader.ProxyNamespace = "http://myappns.com/"; //the namespace of the XmlTypeAttribute reader.ProxyType = typeof(ProxysNamespace.Person); //the type with the XmlTypeAttribute //deserialize listB = (List<ProxysNamespace.Person>)serializer.Deserialize(reader); } //display list foreach (ProxysNamespace.Person p in listB) { Console.WriteLine(p.ToString()); } Console.ReadLine(); } } public class Person { public string Name { get; set; } public int Age { get; set; } public DateTime StartDate { get; set; } public decimal Money { get; set; } } namespace ProxysNamespace { [XmlTypeAttribute(Namespace = "http://myappns.com/")] public class Person { public string Name { get; set; } public int Age { get; set; } public DateTime Birthday { get; set; } public decimal Money { get; set; } public override string ToString() { return string.Format("{0}:{1},{2:d}:{3:c2}", Name, Age, Birthday, Money); } } } public class XmlSoapProxyReader : XmlTextReader { List<object> propNames; public XmlSoapProxyReader(Stream input) : base(input) { propNames = new List<object>(); } public string ProxyNamespace { get; set; } private Type proxyType; public Type ProxyType { get { return proxyType; } set { proxyType = value; PropertyInfo[] properties = proxyType.GetProperties(); foreach (PropertyInfo p in properties) { propNames.Add(p.Name); } } } public override string NamespaceURI { get { object localname = LocalName; if (propNames.Contains(localname)) return ProxyNamespace; else return string.Empty; } } }
Для десериализации XML без пространства имен добавьте атрибут XmlRoot в класс, представляющий вершину иерархии:
[XmlRoot(ElementName="plugins", Namespace="")]В моем примере Xml не имеет пространства имен и начинается как
<plugins><...Класс, в который он десериализуется:
[XmlRoot(ElementName="plugins", Namespace="")] public class Plugins { //... }Очевидно, что ваша ситуация может быть немного другой, но этот код работает для меня:
using (FileStream stream = File.Open(filePath, FileMode.Open)) { XmlReader reader = new XmlTextReader(stream); XmlSerializer serializer = new XmlSerializer(typeof(Plugins)); var plugins = (Plugins)serializer.Deserialize(reader); }- Стэн
Вы можете прочитать файл в виде текста, удалить оскорбительный текст пространства имен, а затем десериализовать его.
Возможно, вам потребуется записать "хороший" текст обратно в поток [memory / string / etc], чтобы вызвать десериализатор XmlSerializer.
Comments