Почему я должен удалить атрибут xmlns для десериализации моего XML-файла? - PullRequest
4 голосов
/ 22 января 2010

Задача

Я использую Xsd2Code (генератор классов .NET для схемы XSD) в простой схеме файла настроек. По какой-то причине, когда я пытаюсь использовать встроенные методы LoadFromFile() или Deserialize(), я получаю исключение, которое, по-видимому, связано с атрибутами xmlns в моих файлах XSD и XML. Если я удалю эти атрибуты, исключение исчезнет. (См. Мое « обновление » ниже для получения подробной информации о коде, который фактически вызывает исключение.)


XSD-файл

<?xml version="1.0" encoding="utf-8"?>
<xs:schema
  xmlns="Myco.CLDatabaseBuilder.Models"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  targetNamespace="Myco.CLDatabaseBuilder.Models"
  elementFormDefault="qualified">
  <xs:element name="Settings" type="Settings" />
  <xs:complexType name="Settings">
    <xs:sequence>
      <xs:element name="SqlServerInstanceName" type="xs:string" />
      <xs:element name="DatabaseName" type="xs:string" />
      <xs:element name="RootDatabaseName" type="xs:string" />
    </xs:sequence>
  </xs:complexType>
</xs:schema>

XML-файл (не удается) - я получаю исключение при попытке десериализации

<?xml version="1.0" encoding="UTF-8"?>
<Settings
  xmlns="Myco.CLDatabaseBuilder.Models"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="Myco.CLDatabaseBuilder.Models Settings.xsd">
  <SqlServerInstanceName>SQLEXPRESS</SqlServerInstanceName>
  <DatabaseName>CL</DatabaseName>
  <RootDatabaseName>master</RootDatabaseName>
</Settings>

XML-файл (успешно) - десериализация работает нормально

<?xml version="1.0" encoding="UTF-8"?>
<Settings
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="Myco.CLDatabaseBuilder.Models Settings.xsd">
  <SqlServerInstanceName>SQLEXPRESS</SqlServerInstanceName>
  <DatabaseName>CL</DatabaseName>
  <RootDatabaseName>master</RootDatabaseName>
</Settings>

Сведения об исключении - что произойдет, если я запусту «пример сбоя»

A first chance exception of type 'System.InvalidOperationException' occurred in System.Xml.dll
System.InvalidOperationException: There is an error in XML document (2, 2). ---> System.InvalidOperationException: <Settings xmlns='Myco.CLDatabaseBuilder.Models'> was not expected.
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderSettings.Read3_Settings()
   --- End of inner exception stack trace ---
   at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
   at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader)
   at Myco.CLDatabaseBuilder.Models.Settings.Deserialize(String xml) in C:\...\CLDatabaseBuilder\Models\Settings.cs:line 118
   at Myco.CLDatabaseBuilder.Models.Settings.LoadFromFile(String fileName) in C:\...\CLDatabaseBuilder\Models\Settings.cs:line 195
   at Myco.CLDatabaseBuilder.Program.InitializeSettings() in C:\...\CLDatabaseBuilder\Program.cs:line 68

Вопросы:

Так что, в принципе, я должен удалить пространство имен по умолчанию, чтобы иметь возможность десериализации.

Любая идея, почему я получаю исключение при использовании xmlns? Это объявление пространства имен очень полезно для выполнения проверки в реальном времени в Visual Studio, поэтому я хотел бы сохранить ее, если это возможно.

Что-то не так с моими атрибутами корневых элементов XSD? Я перепутал с elementFormDefault (меняется с qualified на unqualified), но это не решило проблему.


Обновление

Код, который он фактически задыхается, таков:

Serializer = new System.Xml.Serialization.XmlSerializer(typeof(Myco.CDDatabaseBuilder.Models.Settings));
Serializer.Deserialize(System.Xml.XmlReader.Create(stringReader));

Как показано в приведенном выше исключении, ошибка, которую я получаю:

<Settings xmlns='Myco.CLDatabaseBuilder.Models'> не ожидалось.

Предлагает ли это что-то для поиска в моем Settings классе (классе, созданном Xsd2Code)? В этом классе разбросано [System.Xml.Serialization...] атрибутов. Интересно, что-то отсутствует, или у класса (или сериализатора) нет способа моделирования атрибута по умолчанию xmlns. Любые идеи приветствуются.

Ответы [ 2 ]

8 голосов
/ 22 января 2010

В один из тех дней ... оказалось, что мне нужны были четыре маленьких персонажа.

В Xsd2Code /xa+ есть переключатель, который устанавливает GenerateXMLAttributes = true

По какой-то причине для этого по умолчанию установлено значение false. Ну, это должно быть правдой, если у вас есть атрибут xmlns и вы хотите десериализовать.

3 голосов
/ 22 января 2010

Я не знаю, в чем проблема, но она должна работать. Вы правы, что запутались. Я проверил вашу схему с помощью инструмента xsd.exe, поставляемого с .NET SDK. Он генерирует этот класс из вашей схемы:

[XmlType(Namespace="Myco.CLDatabaseBuilder.Models")]
[XmlRoot(Namespace="Myco.CLDatabaseBuilder.Models", IsNullable=false)]
public partial class Settings {

    private string sqlServerInstanceNameField;

    private string databaseNameField;

    private string rootDatabaseNameField;

    /// <remarks/>
    public string SqlServerInstanceName {
        get {
            return this.sqlServerInstanceNameField;
        }
        set {
            this.sqlServerInstanceNameField = value;
        }
    }

    /// <remarks/>
    public string DatabaseName {
        get {
            return this.databaseNameField;
        }
        set {
            this.databaseNameField = value;
        }
    }

    /// <remarks/>
    public string RootDatabaseName {
        get {
            return this.rootDatabaseNameField;
        }
        set {
            this.rootDatabaseNameField = value;
        }
    }
}

Как вы можете видеть, есть несколько атрибутов, украшающих класс. Есть XmlType и XmlRoot, и все. Три свойства в этом классе неявно сериализуются, даже без атрибута XmlElement.

Результат, полученный от re -сериализации вашего XML, таков:

<q1:Settings xmlns:q1="Myco.CLDatabaseBuilder.Models">
  <q1:SqlServerInstanceName>SQLEXPRESS</q1:SqlServerInstanceName>
  <q1:DatabaseName>CL</q1:DatabaseName>
  <q1:RootDatabaseName>master</q1:RootDatabaseName>
</q1:Settings>
...