Desserializar xml com prefixos de namespace que são indefinido
-
05-07-2019 - |
Pergunta
A resposta XML que recebo é a seguinte:
<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>
A minha turma é decorado como tal:
[XmlElement("item")]
public Item[] Items{get;set;}
[XmlElement("otherValue")
public string OtherValue{get;set;}
Quando tento desserializar o XML acima para a classe descrita, recebo um erro de "Namespace prefixo 'java' não está definido". Adicionando o atributo "namespace" para a classe resolve o erro de análise (no entanto, o XML é então distorcida do original).
ie
[XmlElement(ElementName="item",Namespace="java")]
Como eu deveria estar decorando uma determinada propriedade para corresponder-se com um novo namespace? Ou, como faço para definir corretamente o namespace?
Eu não estou 100% sobre o uso de uma matriz de ações para minha seção enumeráveis ??quer, mas eu acho que a questão namespace leva precident no momento. Qualquer insight ou pensamentos são muito apreciados!
UPDATE:
Eu acho que a questão é melhor reformulada agora que eu voltar se foi e para trás um pouco:
Como você usa um XmlElementAttribute (ou outro atributo) para ter uma classe que pode serializar para o item trecho acima, incluindo as marcas XSI?
Como para o meu problema particular, eu realizei desde que a resposta XML é fora do meu controle, eu não preciso dos atributos xsi para começar. Para solucionar o problema serialização Estou apenas fazendo o seguinte (elemento XmlElement contém o documento original acima):
foreach(XmlNode node in element)
node.Attributes.RemoveAll();
Eu estou apenas observando a minha solução pessoal como este não é realmente uma solução.
Solução
Infelizmente este é um XML válido, e completamente em conformidade com o padrão XML. É valida, é correto e é completa.
O problema que você está tendo é na desserialização, que não é uma parte do padrão XML e está relacionado com tipos XML como .NET mapas declarados para tipos CLR internos.
O xsi: type é uma referência ao namespace e destina-se a permitir que documentos XML para substituir um tipo de derivado de outro namespace para o tipo declarado no esquema.
Eu sei da minha própria experiência que programadores tendem a reagir em estado de choque que este tipo de coisa é mesmo legal, XML muito menos correto. Ele basicamente seqüestra seu esquema.
Você não precisa sequer precisa incluir o namespace estrangeira para que esta seja considerada correta.
(veja este artigo para mais ranting sobre este assunto: http: // Norman. walsh.name/2004/01/29/trainwreck )
Agora, sobre a forma de lidar com o seu problema declarou: desserializar essa bagunça. 1) processar o texto XML e remover a declaração xsi-tipos e espero que não existem campos declarados que se estendem do tipo base. 2) declarar um tipo que deriva de seu tipo base no esquema.
Este parece ser o seguinte:
// 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
{
...
}
Este é apenas um esboço, espero que o suficiente para você começar. Note-se que este não é um problema fácil de resolver progmatically porque é sempre possível para alguém para alimentá-lo XML e irá validar, mas não desserializar corretamente.
Outras dicas
Você estava certo da primeira vez. "Java" não é um espaço de nomes. É um prefixo namespace. Isso é uma abreviação do namespace, para uso no XML. Caso contrário, o namespace real teria que ser repetido sempre que você vê atualmente "java:".
Você pode usar List<Item>
vez de Item[]
.