Como desserializar este documento XML:
<?xml version="1.0" encoding="utf-8"?>
<Cars>
<Car>
<StockNumber>1020</StockNumber>
<Make>Nissan</Make>
<Model>Sentra</Model>
</Car>
<Car>
<StockNumber>1010</StockNumber>
<Make>Toyota</Make>
<Model>Corolla</Model>
</Car>
<Car>
<StockNumber>1111</StockNumber>
<Make>Honda</Make>
<Model>Accord</Model>
</Car>
</Cars>
Eu tenho isto:
[Serializable()]
public class Car
{
[System.Xml.Serialization.XmlElementAttribute("StockNumber")]
public string StockNumber{ get; set; }
[System.Xml.Serialization.XmlElementAttribute("Make")]
public string Make{ get; set; }
[System.Xml.Serialization.XmlElementAttribute("Model")]
public string Model{ get; set; }
}
.
[System.Xml.Serialization.XmlRootAttribute("Cars", Namespace = "", IsNullable = false)]
public class Cars
{
[XmlArrayItem(typeof(Car))]
public Car[] Car { get; set; }
}
.
public class CarSerializer
{
public Cars Deserialize()
{
Cars[] cars = null;
string path = HttpContext.Current.ApplicationInstance.Server.MapPath("~/App_Data/") + "cars.xml";
XmlSerializer serializer = new XmlSerializer(typeof(Cars[]));
StreamReader reader = new StreamReader(path);
reader.ReadToEnd();
cars = (Cars[])serializer.Deserialize(reader);
reader.Close();
return cars;
}
}
que não parecem funcionar :-(
Respostas:
Aqui está uma versão de trabalho. Alterei os
XmlElementAttribute
rótulos para,XmlElement
porque no xml os valores StockNumber, Make e Model são elementos, não atributos. Também removi oreader.ReadToEnd();
(essa função lê todo o fluxo e retorna uma string, para que aDeserialize()
função não pudesse mais usar o leitor ... a posição estava no final do fluxo). Eu também tomei algumas liberdades com a nomeação :).Aqui estão as aulas:
A função desserializar:
E o xml ligeiramente aprimorado (eu precisava adicionar um novo elemento para agrupar <Cars> ... Net é exigente quanto à desserialização de matrizes):
fonte
[Serializable]
é redundante se estiver usandoXmlSerializer
;XmlSerializer
simplesmente nunca verifica isso. Da mesma forma, a maioria dos[Xml...]
atributos é redundante, pois simplesmente imita o comportamento padrão; ou seja, por padrão, uma propriedade chamadaStockNumber
é armazenada como um elemento chamado<StockNumber>
- não há necessidade de atributos para isso.Que tal salvar o xml em um arquivo e usar o xsd para gerar classes C #?
xsd foo.xml
xsd foo.xsd /classes
Et voila - e arquivo de código C # que deve poder ler os dados via
XmlSerializer
:(inclua os foo.cs gerados no projeto)
fonte
Você tem duas possibilidades.
Método 1. Ferramenta XSD
Suponha que você tenha seu arquivo XML neste local
C:\path\to\xml\file.xml
Você pode encontrá-lo em
Start Menu > Programs > Microsoft Visual Studio 2012 > Visual Studio Tools
Ou, se você possui o Windows 8, pode começar a digitar Prompt de Comando do Desenvolvedor na tela Iniciarcd /D "C:\path\to\xml"
xsd file.xml
xsd /c file.xsd
E é isso! Você gerou classes C # do arquivo xml em
C:\path\to\xml\file.cs
Método 2 - Colar especial
Visual Studio 2012+ necessário
Edit > Paste special > Paste XML As Classes
E é isso!
Uso
O uso é muito simples com esta classe auxiliar:
Tudo o que você precisa fazer agora é:
fonte
Paste XML As Classes
alvos de comando única .NET 4.5O seguinte snippet deve fazer o truque (e você pode ignorar a maioria dos atributos de serialização):
...
fonte
Veja se isso ajuda:
.
Caso contrário, use o programa xsd.exe que acompanha o visual studio para criar um documento de esquema com base nesse arquivo xml e, em seguida, use-o novamente para criar uma classe com base no documento de esquema.
fonte
Não acho que .net seja "exigente quanto à desserialização de matrizes". O primeiro documento xml não está bem formado. Não há elemento raiz, embora pareça que exista. O documento xml canônico possui uma raiz e pelo menos 1 elemento (se houver). No seu exemplo:
fonte
tente este bloco de código se o seu arquivo .xml foi gerado em algum lugar do disco e se você usou
List<T>
:Nota:
C:\serialize.xml
é o caminho do meu arquivo .xml. Você pode alterá-lo para suas necessidades.fonte
A ansiedade de Kevin é boa, além do fato de que, no mundo real, muitas vezes você não pode alterar o XML original para atender às suas necessidades.
Também existe uma solução simples para o XML original:
E então você pode simplesmente ligar para:
fonte
Experimente esta classe genérica para serialização e desserialização de XML.
fonte
Para iniciantes
Achei as respostas aqui muito úteis, que diziam que ainda lutava (apenas um pouco) para fazer isso funcionar. Portanto, caso ajude alguém, explicarei a solução de trabalho:
XML da pergunta original. O xml está em um arquivo Class1.xml, um
path
para esse arquivo é usado no código para localizar esse arquivo xml.Eu usei a resposta de @erymski para fazer isso funcionar, então criei um arquivo chamado Car.cs e adicionei o seguinte:
O outro código fornecido por @erymski ...
... entra no seu programa principal (Program.cs),
static CarCollection XCar()
assim:Espero que ajude :-)
fonte
Que tal uma classe genérica para desserializar um documento XML
Esta parte pode ou não ser necessária. Abra o documento XML no Visual Studio, clique com o botão direito do mouse no XML, escolha propriedades. Em seguida, escolha seu arquivo de esquema.
fonte
Um forro:
fonte
A idéia é ter todos os níveis sendo tratados para desserialização. Consulte uma solução de exemplo que resolveu meu problema semelhante
O XML acima é tratado em dois níveis
O nível interno
Da mesma maneira que você precisa de vários níveis com
car as array
Verifique este exemplo para desserialização multinívelfonte
Se você estiver recebendo erros ao usar o xsd.exe para criar seu arquivo xsd, use a classe XmlSchemaInference, conforme mencionado no msdn . Aqui está um teste de unidade para demonstrar:
fonte
Você pode alterar apenas um atributo para sua propriedade de carro Cars, de XmlArrayItem para XmlElment. Ou seja, de
para
fonte
Minha solução:
Edit > Past Special > Paste XML As Classes
para obter a classe no seu códigoList<class1
>) e use aXmlSerializer
para serializar essa lista em umxml
arquivo.deserialize
fazê - lo.Código:
NOTA: você deve prestar atenção ao nome raiz, não o altere. O meu é "ArrayOfClass1"
fonte
fonte