Я сейчас нахожусь в процессе создания группы файлов, которые затем будут использоваться другой программой. Большинство из них являются XML-файлами. Естественно, я извлек файлы .xsd из программы и использовал инструмент xsd.exe для автоматической генерации C # -классов, который работает довольно хорошо.
Проблема
Сериализация автоматически сгенерированного класса приводит к xml-файлу, подобному этому:
<root xmlns="ns1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<group xmlns="">
<item>foo</item>
<item>bar</item>
</group>
</root>
И xsi
, и xsd
не используются во всем, что я нашел до сих пор, но это не должно быть проблемой.
XML-код, ожидаемый программой, будет выглядеть примерно так:
<n1:root xmlns:n1="ns1">
<group>
<item>foo</item>
<item>bar</item>
</group>
</n1:root
При десериализации оба xml должны приводить к одному и тому же результату, поэтому я не помещаю ошибку в xsd.exe.
Однако при попытке открыть сгенерированный XML-файл в программе выдается ошибка «Ссылка на объект не установлена на экземпляр объекта». И xmlns:xsi
, и xmlns:xsd
должны быть удалены, и он должен использовать xmlns:n1
вместо пространства имен по умолчанию.
Что я пробовал
Сначала я подумал, что мог бы просто сериализовать класс вручную, используя IXmlSerializable
, однако это приводит к ошибке времени выполнения при сериализации, поскольку xsd.exe автоматически добавляет XmlTypeAttribute
и XmlRootAttribute
.
Произведенная ошибка читает InvalidOperationException: Only XmlRoot attribute may be specified for the type myNs.MyClass. Please use XmlSchemaProviderAttribute to specify schema type.
Я не думаю, что использование XmlSchemaProviderAttribute является хорошей идеей, потому что это отвергает идею автоматического создания класса из заданной схемы. (Схема, вероятно, изменится в будущих версиях программы)
Если вам нужен минимальный пример, вот код, который выполняется на rextester.com : (обратите внимание, что rextester использует .NET Framework 4.5, а я использую .NET Framework 4.7, поэтому любые ответы, использующие новые функции приветствуются)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
namespace Rextester
{
// AUTOGENERATED
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.7.2558.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://www.somens.com")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="http://www.somens.com", IsNullable=false)]
public partial class Test {
[System.Xml.Serialization.XmlArrayAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
[System.Xml.Serialization.XmlArrayItemAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=false)]
public Item[] Group { get; set; }
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.7.2558.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://www.somens.com")]
public partial class Item {
[System.Xml.Serialization.XmlAttributeAttribute()]
public int Value { get; set; }
}
// CUSTOM
public partial class Test : IXmlSerializable
{
public XmlSchema GetSchema()
{
return null;
}
public void ReadXml(XmlReader reader)
{
throw new NotImplementedException();
}
public void WriteXml(XmlWriter writer)
{
foreach (var item in Group) {
writer.WriteStartElement("item");
writer.WriteAttributeString("Value", item.Value.ToString());
writer.WriteEndElement();
}
}
}
public class Program
{
public static void Main(string[] args)
{
var t = new Test();
t.Group = new Item[] { new Item { Value = 5}, new Item { Value = 10} };
var serializer = new XmlSerializer(typeof(Test));
serializer.Serialize(Console.Out, t);
}
}
}