Десериализация XML с префиксами пространства имен, которые не определены - PullRequest
3 голосов
/ 29 июля 2009

Xml-ответ, который я получаю, выглядит следующим образом:

<response>
    <item xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="java:com.someDomain.item">
        <name>some name</disc-name>
        <description>some description</disc-desc>
    </item>
    <item xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="java:com.someDomain.item">
            <name>some name</disc-name>
            <description>some description</disc-desc>
    </item>
    <otherValue>12.1</otherValue>
</response>

Мой класс оформлен так:

[XmlElement("item")]
public Item[] Items{get;set;}
[XmlElement("otherValue")
public string OtherValue{get;set;}

Когда я пытаюсь десериализовать вышеупомянутый Xml в описанный класс, я получаю сообщение об ошибке «Префикс пространства имен« java »не определен». Добавление атрибута «namespace» к классу устраняет ошибку синтаксического анализа (однако затем xml искажается от оригинала).

е

[XmlElement(ElementName="item",Namespace="java")]

Как мне оформить данное свойство, чтобы оно соответствовало новому пространству имен? Или как правильно определить пространство имен?

Я не на 100% использую массив массива для моего перечислимого раздела, но я думаю, что проблема с пространством имен в настоящее время становится более важной. Любое понимание или мысли с благодарностью!

UPDATE:

Я думаю, что вопрос лучше перефразировать теперь, когда я немного перебрал:

Как вы используете XmlElementAttribute (или другой атрибут), чтобы иметь класс, который можно сериализовать во фрагмент кода выше, включая теги xsi?

Что касается моей конкретной проблемы, я понял, так как ответ Xml находится вне моего контроля, мне не нужны атрибуты xsi для начала. Чтобы обойти проблему сериализации, я просто делаю следующее (элемент XmlElement содержит исходный документ выше):

foreach(XmlNode node in element)
node.Attributes.RemoveAll();

Я только отмечаю мой личный обходной путь, поскольку на самом деле это не решение.

Ответы [ 2 ]

1 голос
/ 29 июля 2009

Вы были правы в первый раз. «Java» не является пространством имен. Это префикс пространства имен. Это сокращение пространства имен, для использования в XML. В противном случае фактическое пространство имен нужно будет повторять везде, где вы видите «java:».

Вы можете использовать List<Item> вместо Item[].

0 голосов
/ 30 июля 2009

К сожалению, это допустимый XML и полностью соответствует стандарту XML. Это подтверждает, это правильно, и это завершено.

Проблема, с которой вы столкнулись, заключается в десериализации, которая не является частью стандарта XML и связана с тем, как .NET отображает объявленные типы XML во внутренние типы CLR.

xsi: type является ссылкой на пространство имен и предназначен для того, чтобы документы XML могли заменить производный тип из другого пространства имен для объявленного типа в схеме.

Я знаю по собственному опыту, что кодеры, как правило, реагируют на шок, что такие вещи даже законны, а тем более не совсем корректны. Это в основном угоняет вашу схему.

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

(см. Эту статью для получения дополнительной информации по этому вопросу: http://norman.walsh.name/2004/01/29/trainwreck)

Теперь о том, как справиться с заявленной вами проблемой: десериализовать этот беспорядок 1) обработать текст xml и удалить объявление xsi-types и надеяться, что нет объявленных полей, расширяющих базовый тип. 2) объявите тип, производный от вашего базового типа в схеме.

Это выглядит следующим образом:

// note this "XmlIncludeAttribute" references the derived type.
// note that in .NET they are in the same namespace, but in XML they are in different namespaces.
[System.Xml.Serialization.XmlIncludeAttribute(typeof(DerivedType))]
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://BaseNameSpace")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="http://BaseNameSpace", IsNullable=true)]
public partial class MyBaseType : object
{
...
}

/// <remarks/>
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://DerivedNameSpace")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="http://DerivedNameSpace", IsNullable=true)]
public partial class DerivedType: MyBaseType 
{
...
}

Это только грубый набросок, надеюсь, достаточно, чтобы вы начали. Обратите внимание, что эту проблему решить непросто программно, потому что всегда кто-то может передать вам XML, и он будет проверять, но не десериализовать должным образом.

...