2010-06-03 26 views
15

Próbujesz deserializować niektóre fragmenty xml od dostawcy do obiektów. Problem polega na tym, że otrzymuję nieprawidłowy format na każdym tagu elementu empy. Mogę deserializować obiekt bez problemu, gdy wszystkie elementy mają wartości. Lub puste elementy są anulowane.Deserializuj Xml z pustymi elementami w C#

XML Snippit:

<bla>
<propone/propone>
< propTwo/>
</foo >

C# Klasa:

[Serialilbe()]  
public class foo 
{ 
    public foo(){} 
    [XmlElementAttribute(IsNullable = true)] 
    public int? propOne {get;set;} 
    [XmlElementAttribute(IsNullable = true)] 
    public int? propTwo {get;set;} 
} 

Czy istnieje ustawienie klasy, które można wykonać, aby dostosować parsowanie?
lub
Czy istnieje prosty sposób zastosowania xsl do usunięcia tych elementów?
lub
Czy należy używać regEx do usuwania pustych elementów, aby uniknąć desrializacji?
lub
jeszcze lepszy sposób?

+0

Czy szeregowania za pośrednictwem tego samego interfejsu (czyli klasy XmlSerializer)? –

+0

Na marginesie, XMLSerializer jest bliski bycia przestarzałym.Możesz rozważyć użycie DataContractSerializer. –

Odpowiedz

10

Najbardziej jednorodnym sposobem oczyszczenia tych węzłów wydaje się dodanie filtru RegEx do deserializera.

public static T Deserialize<T>(string xml){ 
     XmlSerializer xs = new XmlSerializer(typeof(T)); 
     string cleanXml = Regex.Replace(xml, @"<[a-zA-Z].[^(><.)]+/>", 
             new MatchEvaluator(RemoveText)); 
     MemoryStream memoryStream = new MemoryStream((new UTF8Encoding()).GetBytes(cleanXml)); 
     XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8); 
     return (T)xs.Deserialize(memoryStream); 
    } 
static string RemoveText(Match m) { return "";} 
+1

Co zrobić, jeśli istnieje kompletny element bez wartości: ''. Napisałem własną logikę, aby to usunąć, ale jest zbyt powolna, a plik za duży. Czy możemy napisać RegEx, aby to wykryć? – MrFox

9

Zobacz ten artykuł: Can XmlSerializer deserialize into a Nullable?

w skrócie swoją XML powinien wyglądać tak, jeśli chcesz używać pustych typy:

<foo xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'> 
<propOne>1</propOne> 
<propTwo xsi:nil='true'/> 
</foo> 

dwóch zmian jest dodanie nazw i jawnie ustawienie xsi : nil na true w elemencie null.

Jeśli nie masz kontroli nad XML jest bardziej zaawansowana technika opisana tutaj: Using XmlSerializer to deserialize into a Nullable

+0

"Korzystanie z XmlSerializer do deserializacji w link zerowy" jest martwe. Jednym ze sposobów na to jest implementacja IXmlSerializable i konwersja pustej na null wewnątrz ReadXml(). Podobny do http://stackoverflow.com/a/625463/1034683 – bodhizero

0

Dla uproszczenia, dlaczego nie można analizować xml explictly użyciu XmlDocument i XPath? Użyj XPath, aby jawnie uzyskać dostęp do każdego węzła XML, np.

+1

Zakładam, że chce deserializować do klasy/typu i nie musi ciągnąć wartości jeden po drugim. – user1040975

8

Innym rozwiązaniem, jeśli nie masz kontroli nad XML przychodzących ma obejść mając Deserializator udawać, że zmienna jest ciągiem:

[Serializable()]  
public class foo 
{ 
    public foo(){} 

    [XmlElement("propOne")] 
    [EditorBrowsable(EditorBrowsableState.Never)] 
    public string propOneString {get;set;} 

    [XmlIgnore] 
    private int? propOneInternal = null; 
    [XmlIgnore] 
    private bool propOneSet = false; 

    [XmlIgnore] 
    public int? propOne 
    { 
    get 
    { 
     if (!propOneSet) 
     { 
     if(!string.IsNullOrEmpty(propOneString) 
     { 
      propOneInternal = int.Parse(propOneString); 
     } 
     //else leave as pre-set default: null 
     propOneSet = true; 
     } 
     return propOneInternal; 
    } 
    set { propOneInternal = value; } 
    } 
} 

Deserialiser z przyjemnością analizuje element łańcuchowy, gdy jest pusty, więc możesz go użyć.

To nie jest szczególnie miłe, ale będzie to zrobić, jeśli masz tylko jedną lub 2 znaczniki na pokrycie

+0

EDYCJA: propOneString powinien oczywiście być ciągiem, a nie intem :) – Brondahl

+0

Tak, najprostszy sposób dla mnie. Po prostu miał jeden tag do czynienia. Dzięki! – GibralterTop

Powiązane problemy