2009-09-14 10 views
11

Mam dość szczegółowy plik xml. Poniżej jest węzły najwyższego poziomu (I zostały objęte elipsy jako dolna węzłów szczebla są dobrze uformowane i właściwie wypełnione danymi):Problemy z deserializacją XML w klasach generowanych przez XSD

<?xml version="1.0" encoding="UTF-8"?> 
<config> 
    <Models>...</Models> 
    <Data>...</Data> 
</config> 

Stworzyłem plik xsd z użyciem Studio 2008 wiersz polecenia programu Visual:

xsd sample.xml 

Generuje plik xsd dobrze. I wtedy automatycznie wygenerować klas z xsd za pomocą polecenia:

xsd sample.xsd /classes 

Dla deserializacji pliku XML do obiektu klasy, używam funkcji odczytu w klasie pomocnika:

public class XmlSerializerHelper<T> 
{ 
    public Type _type; 

    public XmlSerializerHelper() 
    { 
     _type = typeof(T); 
    } 

    public void Save(string path, object obj) 
    { 
     using (TextWriter textWriter = new StreamWriter(path)) 
     { 
      XmlSerializer serializer = new XmlSerializer(_type); 
      serializer.Serialize(textWriter, obj); 
     } 
    } 

    public T Read(string path) 
    { 
     T result; 
     using (TextReader textReader = new StreamReader(path)) 
     { 
      XmlSerializer deserializer = new XmlSerializer(_type); 
      result = (T)deserializer.Deserialize(textReader); 
     } 
     return result; 
    } 
} 

kiedy próbuje się deserializacji z:

var helper = new XmlSerializerHelper<configModels>(); 
var obj = new configModels(); 
obj = helper.Read(filepath); 

otrzymuję błąd, że mam wywiedziona jest ponieważ Deserializator szuka węzła „modeli”, ale odpowiednia nazwa klasy została generat ed jako połączenie węzła głównego i węzła "Model" (configModels). Dlaczego nazwy klas są generowane w ten sposób?

Próbowałem deserializowania z górnego węzła przy użyciu:

var helper = new XmlSerializerHelper<config>(); 
var obj = new config(); 
obj = helper.Read(filepath); 

Niestety, wyniki w mnóstwem błędów jak następuje:

System.InvalidOperationException was unhandled by user code 
Message="Unable to generate a temporary class (result=1). 
error CS0030: Cannot convert type 'Application.Lease[]' to 'Application.Lease' 
error CS0030: Cannot convert type 'Application.CashFlow[]' to 'Application.CashFlow' 
...ect. 

Może ktoś pokierować mnie do tego, co może robić źle przy moim generowaniu automatycznie przez xsd?

+0

Żadne z automatycznych narzędzi nie wygenerowałoby poprawnego kodu. Ręcznie napisałem kod obiektowy dla xml do deserializacji. –

+0

Czy możesz zaznaczyć odpowiedź marc_s jako poprawną, ponieważ powiedziałeś, że rozwiązał twój problem? – Win

Odpowiedz

3

Wystąpił problem z plikiem xsd.exe i listami. Musisz przejść do wygenerowanej klasy i ręcznie edytować plik do poprawnego typu. Przełączyłem się na Xsd2Code. Do tej pory wydaje się, że nie ma tego problemu.

+0

Po prostu próbowałem Xsd2Code i również daje mi te same błędy konwersji z list. –

+0

Czy nie powinienem używać xsd.exe do automatycznego generowania pliku xsd? –

+0

Możesz go używać w porządku. Musisz po prostu przejść do wygenerowanej klasy i edytować ją ręcznie. Jednak gdyby Xsd2Code również miał problemy, musiałbym zgodzić się z @marc_s; Prawdopodobnie przyczyną problemu jest coś w twoim schemacie XML. –

10

XSD.EXE to dobry początek - ale daleko mu do ideału. Ponadto, na podstawie podanego kodu XML, XSD.EXE nie zawsze może zdecydować, czy coś jest pojedynczą instancją obiektu, czy otwartą tablicą obiektów.

Wydaje się, że dotyczy to dwóch elementów - Application.Lease i Application.CashFlow. W jaki sposób są one zdefiniowane w wygenerowanym pliku XSD? Czy to ma dla ciebie sens? Całkiem możliwe, że trzeba dodać trochę podpowiedzi, takie jak:

<xs:element name="Lease" minOccurs="0" maxOccurs="1" /> 

dla opcjonalnej właściwości, to tylko zero lub jeden occurences. Takie rzeczy są naprawdę trudne do znalezienia przez narzędzie xsd.exe w oparciu o pojedynczy przykładowy plik XML.

Marc

+1

Marc, masz rację, pieniądze rozwiązały problem dla mnie. Ręczne aktualizowanie wartości minOccurs i maxOccurs na elementach naruszających zasady, a następnie uruchomienie XSD2CODE w celu wygenerowania moich klas rozwiązało ten problem dla mnie. – ProNotion

10

idź do generowanej klasy i zmienić wszystko od [] [] ---> []

+0

Podczas gdy rozwiąże to problem, odpowiedź marc_s zawiera wyjaśnienie, dlaczego jest to konieczne i jak tego uniknąć. – MyItchyChin

0

Kolejną kwestią, która może być przyczyną tego problemu jest to, że zawartość pliku XML pomiędzy znacznikami (czyli zawartość) jest nadal zakodowana, gdy nie powinno być. Na przykład znaczniki <br> w mojej zawartości nadal były <br> zamiast &lt;br /&gt;. Generator xsd przekształcił je w elementy schematu, a następnie błędnie oznaczono je jako nieograniczone, ponieważ znaleziono więcej niż jeden.Odkodowanie ich rozwiązało problem i poprawnie wygenerowało klasy.