Newsgroup: it.comp.lang.visual-basic
Titolo: [VB2010] Deserializzare XML custom (+ XSD tool)

Salve a tutti,
questa volta sono proprio inchiodato.
Ho un file XML, che mi arriva da una procedura legacy (in realtà sono alcune decine di diversi file XML, ma per semplicità restiamo su un solo file)
 
Questo file mi arriva ogni notte in una cartella. Io devo caricarlo e prendere alcuni valori.
 
Allora mi sono detto: uso l'ottimo tool XSD di Visual Studio 2010!
 
Il file xml è questo:
http://dl.dropbox.com/u/7161916/tmp/Inflation_Individual.xml
 
 
Seguo passo passo ciò che è descritto in questo sito:
http://sharpertutorials.com/using-xsd-tool-to-generate-classes-from-xml/
 
 
Quindi apro la command line dai Tool di VS2010
xsd Inflation_Individual.xml
xsd Inflation_Individual.xsd /classes /language:vb
 
Mi vengono quindi generati i file Inflation_Individual.xsd ed Inflation_Individual.vb
 
A questo punto li importo nel mio progetto ed ecco il primo errore:
http://dl.dropbox.com/u/7161916/tmp/err1.png
 
 
Poco male, siccome è una partial class e le cose vengono duplicate (poi voglio capire perchè, visto che il codice è creato da XSD che è un tool di visual studio), elimino l'intera parte incriminata:
http://dl.dropbox.com/u/7161916/tmp/err2.png
 
 
Qui inizia il vero problema.
Quando provo a deserializzare ottengo il seguente errore:
http://dl.dropbox.com/u/7161916/tmp/err3.png
 
 
E qui ci ho sbattuto la testa ore! Ho cercato invano su google ma il problema non si risolve.
 
La cosa più assurda è che, se provo ad eseguire passo passo la guida di cui sopra ( 
http://sharpertutorials.com/using-xsd-tool-to-generate-classes-from-xml/
 ) utilizzando il file "CD Catalog" (
http://www.w3schools.com/XML/cd_catalog.xml
) il problema non si pone!
 
A questo punto mi viene da pensare che il problema sia nell'XML di input.
 
Qualcuno di voi si è mai imbattuto in questo problema?
Se necessario posso anche inviare un progettino pre-confezionato per effettuare delle prove.
Grazie,
 
Nicola
 
 
 

 
http://dl.dropbox.com/u/7161916/tmp/err2.png
 
 
Prima di tutto grazie della segnalazione perché ho giusto
un problema simile: devo interpretare degli XML e stavo
per mettermi a farlo a mano :-).
 
Allora, ho fatto delle prove con un XML che avevo io e
all'inizio ho riscontrato lo stesso problema.
Poi ho scoperto che se c'è già il .vb creato da XSD.exe
nella cartella, quando vai ad importare il .xsd il .vb
viene modificato. Quindi ho riprovato da capo:
* Creato un progetto pulito
* usato i XSD per creare il .xsd (col namespace incluso,
   come indicato nei commenti del sito linkato) e il .vb
* copiato nella cartella del progetto il .xsd
* importato l'xsd, l'IDE ha creato vari altri file.
* copiato nella cartella del progetto il .vb
* importato nel progetto il .vb
 
Nessun errore, fin qui.
Ho scaricato il file tuo e ho seguito lo stesso percorso,
idem come sopra: nessun errore, compila regolarmente.
Ovviamente non *fa* niente, ma...
 
 > Qui inizia il vero problema.
 > Quando provo a deserializzare ottengo il seguente errore:
 
Ora, visto che sono un niubbo al quadrato con .NET, con
l'XML, con la serializzazione e coi namespace, una domanda
la faccio io... come vado avanti, cioè: come faccio a
deserializzare un qualche cosa ? :-D
 
Dai, che magari in due... beh, diciamo uno tu e un quarto io,
ne usciamo :-)
 
Bye, G.

 
"Paperino" <non...@lo.dico.invalid> ha scritto nel messaggio 
news:jkg21a$rk2$1...@dont-email.me...
 
ciao, mi inserisco per dirti una cosa, visto che tutto sommato siamo 
geograficamente vicini.
Posso porti un certo problemino di programmazione ? 
 
 

 Qualcuno di voi si è mai imbattuto in questo problema?
 
a naso il problema è tutto legato al namespace che il serializzatore 
trova nel file me che non sa come trattare, hai provato a specificare 
il namespace nel costruttore?
http://msdn.microsoft.com/en-US/library/kw0f5wee(v=vs.80).aspx
 
 
.m
 
-- 
blog @ //
milestone.topics.it
 
 
 

 Posso porti un certo problemino di programmazione ?
 
La mail nel reply-to č buona, ma non garantisco
di leggerla (o nel caso, di risolvere qualcosa)
in tempi brevi: ho un paio di giorni di riposo,
e la moglie che praticamente neanche mi vede da
un po'... tu intanto anticipa qualcosa, poi nel
caso ci si vede di persona :-).
 
Bye, G. 
 
 

 deserializzare un qualche cosa ? :-D
 
Deserializzi così:
 
 Public Function ConvertXML(ByVal PercorsoXML As String, ByVal TipoFile As String) As String
 
        Dim str As New StreamReader(PercorsoXML)
        Dim xSerializer As New XmlSerializer(GetType(NewDataSet))
        Dim tmpClasseXML As NewDataSet = xSerializer.Deserialize(str)
 
 
        Console.WriteLine()
 
        str.Close()
 
        Return "+OK"
    End Function
 
Il problema è che mi restituisce l'errore di cui parlavo ( 
http://dl.dropbox.com/u/7161916/tmp/err3.png
 ) in fase di deserializzazione.
 
Nicola
 


Ciao Mauro,
scusa ma magari mi manca qualche informazione (purtroppo sulla serializzazione/deserializzazione sono ancora all'inizio, soprattutto se si tratta di XML che mi vengono forniti AS-IS sui quali non ho potere decisionale).
 
Io ho aggiunto il namespace nella costruzione dell'istanza di XmlSerializer, ma il problema sembra presentarsi ancora, come puoi vedere dallo screenshot seguente:
http://dl.dropbox.com/u/7161916/tmp/err4.png
 
 
Sono io che sto sbagliando ancora qualcosa o può essere un problema\limite delle classi XML di .NET?
 
Grazie,
 
Nicola

Allora,
sono riuscito a risolvere!
 
Innanzitutto sbagliavo io a puntare sul tipo "NewDataSet", mi sono fatto fuorviare dall'articolo qui: 
http://sharpertutorials.com/using-xsd-tool-to-generate-classes-from-xml/
 
 
Infatti, seguendo l'esempio dell'articolo (ed usando il file xml "CD Catalog") si genera un file xsd con proprietà Name = "CATALOG".
Il mio file generava un xsd con proprietà Name = "NewDataSet".
 
Quindi mi veniva naturale fare così:
 
 
Dim str As New StreamReader(PercorsoXML)
Dim xSerializer As New XmlSerializer(GetType(NewDataSet))
Dim tmpClasseXML As NewDataSet = xSerializer.Deserialize(str)
 
INVECE NO!
 
Dovevo prendere sempre il primo nodo padre del mio xml, quindi InflationEvaluationOutput
 
Dim str As New StreamReader(PercorsoXML)
Dim xSerializer As New XmlSerializer(GetType(InflationEvaluationOutput))
Dim tmpClasseXML As InflationEvaluationOutput= xSerializer.Deserialize(str)
 
 
 
 
E qui qui scatta un problema di .NET (subdolo e bastardo da morire!!!)
 
Infatti ricevevo sempre questo errore:
http://dl.dropbox.com/u/7161916/tmp/err5.png
 
 
(incollo lo stesso errore in formato testo per i posteri)
 
Unable to generate a temporary class (result=1).
error CS0030: Cannot convert type 'AdHocXMLConverter.cashFlow[]' to 'AdHocXMLConverter.cashFlow'
error CS0030: Cannot convert type 'AdHocXMLConverter.cashFlow[]' to 'AdHocXMLConverter.cashFlow'
 
 
 
Gira che ti rigira (ho perso ore sulla knowledge base e su google), trovo questo post:
http://forums.asp.net/t/1469891.aspx/1
 
 
Il problema, quindi, è un maledetto bug di Visual Studio!
 
E' stato quindi sufficiente sostituire tutte le "()()" con "()" nel file Inflation_Individual.vb (quello generato con il comando "xsd Inflation_Individual.xsd /c /language:vb"), come potete qui:
http://dl.dropbox.com/u/7161916/tmp/soluzione.png
 
 
(incollo la soluzione in formato testo per i posteri)
 
PRIMA:
 
Private evaluationCharacteristicsField() As InflationEvaluationOutputEvaluationCharacteristics
Private cashFlowsField()() As cashFlow
Private notionalCashFlowsField()() As cashFlow
Private additionalCashFlowsField()() As cashFlow
 
DOPO:
 
Private evaluationCharacteristicsField() As InflationEvaluationOutputEvaluationCharacteristics
Private cashFlowsField() As cashFlow
Private notionalCashFlowsField() As cashFlow
Private additionalCashFlowsField() As cashFlow
 
E quindi ora funziona e deserializza correttamente l'XML!!!
 
 
Nicola
 
 

 
http://dl.dropbox.com/u/7161916/tmp/err5.png
 



 > Infatti, seguendo l'esempio dell'articolo (ed usando il file
 > xml "CD Catalog")
 > si genera un file xsd con proprietà Name = "CATALOG".
 > Il mio file generava un xsd con proprietà Name = "NewDataSet".
 > Quindi mi veniva naturale fare così:
 > Dim str As New StreamReader(PercorsoXML)
 > Dim xSerializer As New XmlSerializer(GetType(NewDataSet))
 > Dim tmpClasseXML As NewDataSet = xSerializer.Deserialize(str)
 > INVECE NO!
 > Dovevo prendere sempre il primo nodo padre del mio xml,
 > quindi InflationEvaluationOutput
 
Questo io ero riuscito ad evitarlo: avevo fatto riferimento
a un qualche altro suggerimento che ora non ritrovo, e alle
info della guida in linea :-).
Tra l'altro, prima che tu mi rispondessi, avevo copiato
il tuo codice leggendolo da una delle PNG :-D.
 
 > Dim str As New StreamReader(PercorsoXML)
 > Dim xSerializer As New XmlSerializer(GetType(InflationEvaluationOutput))
 > Dim tmpClasseXML As InflationEvaluationOutput= 
xSerializer.Deserialize(str)
 > E qui qui scatta un problema di .NET (subdolo e bastardo da morire!!!)
 > Infatti ricevevo sempre questo errore:
 > 
http://dl.dropbox.com/u/7161916/tmp/err5.png
 
 > Gira che ti rigira (ho perso ore sulla knowledge base
 > e su google), trovo questo post:
 > 
http://forums.asp.net/t/1469891.aspx/1
 
 > Il problema, quindi, è un maledetto bug di Visual Studio!
 
[inserire qui imprecazioni a piacere]
 
 > E' stato quindi sufficiente sostituire tutte le "()()"
 > con "()" nel file Inflation_Individual.vb (quello generato
 > con il comando "xsd Inflation_Individual.xsd /c /language:vb"),
[CUT]
 > E quindi ora funziona e deserializza correttamente l'XML!!!
 
OK, a questo punto ho provato con uno dei miei XML
che, forse perché sono molto più semplici, non fanno
scattare quel bug.
 
Sono riuscito a deserializzare, ma anche avendo i dati
nella classe ci ho messo due ore prima di riuscire a
capire come tirarli fuori... e anch'io ho scoperto che
non era tutta colpa mia: è proprio che i dati nell'XML
sono stati scritti con una logica da cuoco: "ficca il
ripieno nel pollo finché non è ben gonfio, poi ricucilo".
A cosa [censura] serva usare un sistema ordinato di
tabelle per poi ficcare tutto a casaccio dentro due
righe in tutto proprio non arrivo a capirlo :-(.
Alla fine sono riuscito ad arrivare ai dati, ma è
stata dura.
 
Grazie ancora di tutto :-)
 
Bye, G.

 [inserire qui imprecazioni a piacere]
 
Sempre per eventuali futuri poveracci che dovessero
capitare su questo thread, segnalo che ce n'è anche
un altro, conosciuto dal 2005 e forse prima.
 
Sulla stessa riga vengono create altre due eccezioni
alla volta, che appaiono nella "finestra di controllo
immediato" così:
"Eccezione first-chance di tipo 'System.IO.FileNotFoundException'
in mscorlib.dll"
 
Attivando la gestione delle eccezioni nel CRL viene
fuori 'sta roba qui:
****************
BindingFailure è stata rilevata
Message: Impossibile caricare l'assembly con nome visualizzato 'Leggi 
Timone.XmlSerializers' nel contesto di associazione 'LoadFrom' del 
dominio di applicazione con ID 1. Causa dell'errore: 
System.IO.FileNotFoundException: Impossibile caricare il file o 
l'assembly 'Leggi Timone.XmlSerializers, Version=1.0.0.0, 
Culture=neutral, PublicKeyToken=null' o una delle relative dipendenze. 
Impossibile trovare il file specificato.
****************
Da quello che ho potuto capire guglando, per motivi
prestazionali al primo avvio di xmlserializer il CRL
va a controllare se esiste già un assembly pronto
specifico e nel caso lo carica, altrimenti lo crea.
Ma il CLR, invece di controllare prima se il file
c'è con un benedetto Filexists, usa un try-catch,
generando l'errore. E lo fa da almeno sette anni:
www.google.it/search?q=file+not+found+xmlserializers
 
 
Ma aggiustare una volta per tutte 'sta cosa pare brutto ?
 
**************
 
La buona notizia è che l'errore può essere ignorato,
disattivando il controllo delle eccezioni del CRL,
oppure può essere evitato a monte (a quanto pare,
non ho ancora provato) generando prima l'assembly
necessario con SGEN:
http://msdn.microsoft.com/en-us/library/bk3w6240%28v=vs.80%29.aspx
 
 
Bye, G.