2009-07-22 11 views
4

Je suis en train de sérialiser un objet qui contient des données HTML dans une propriété String.Sérialisation XML d'un objet contenant des caractères invalides

Dim Formatter As New Xml.Serialization.XmlSerializer(GetType(MyObject)) 
Dim fs As New FileStream(FilePath, FileMode.Create) 
Formatter.Serialize(fs, Ob) 
fs.Close() 

Mais quand je lis le XML à l'objet:

Dim Formatter As New Xml.Serialization.XmlSerializer(GetType(MyObject)) 
Dim fs As New FileStream(FilePath, FileMode.Open) 
Dim Ob = CType(Formatter.Deserialize(fs), MyObject) 
fs.Close() 

Je reçois cette erreur:

"'', hexadecimal value 0x14, is an invalid character. Line 395, position 22." 

ne devrait pas empêcher .NET ce genre d'erreur, échapper aux caractères invalides?

Que se passe-t-il ici et comment puis-je le réparer?

Répondre

2

Il aurait dû échoué à l'étape de sérialisation, parce que 0x14 is an invalid value for XML. Il n'y a aucun moyen de l'échapper, même avec &#x14, car il est exclu en tant que caractère valide du modèle XML. Je suis vraiment surpris que le sérialiseur le laisse passer, car il rend le sérialiseur non-conforme.

Est-il possible pour vous de supprimer les caractères non valides de la chaîne avant de sérialisation il? Dans quel but avez-vous un 0x14 en HTML?

Ou, est-il possible que vous écrivez avec un encodage et la lecture avec un autre?

+0

Eh bien, je suis allé avec cette solution. J'ai supprimé les caractères invalides de la chaîne avant la sérialisation. Mais, je ne comprends toujours pas pourquoi XmlSerializer ne désérialise pas un objet qui a été sérialisé. – InfoStatus

+0

Vous êtes en bonne forme, à moins que les caractères invalides soient réellement importants. –

+1

J'ai trouvé une description plus complète de ce problème ici: http://seattlesoftware.wordpress.com/2008/09/11/hexadecimal-value-0-is-an-invalid-character/ – Derrick

0

J'exepct .NET pour gérer cela, mais vous pouvez également consulter la classe XmlSerializer et XmlReaderSettings (voir l'exemple méthode générique ci-dessous):

public static T Deserialize<T>(string xml) 
{ 
    var xmlReaderSettings = new XmlReaderSettings() 
           { 
            ConformanceLevel = ConformanceLevel.Fragment, 
            ValidationType = ValidationType.None 
           }; 

    XmlReader xmlReader = XmlTextReader.Create(new StringReader(xml), xmlReaderSettings); 
    XmlSerializer xs = new XmlSerializer(typeof(T), ""); 

    return (T)xs.Deserialize(xmlReader); 
} 

Je vérifie aussi s'il n'y a pas de codage (Unicode , UTF8, etc.) dans votre code. La valeur hexadécimale 0x14 est pas char que vous attendez en XML :)

+0

-1 pour: ne pas utiliser de blocs, en utilisant XmlTextReader, suggérant une solution sans connaître le problème. –

+0

Quel est le problème de ne pas utiliser les blocs 'using'? – Ian

+1

Fuites de ressources. XmlReader et StringReader implémente IDisposable. –

1

Vous devriez vraiment afficher le code de la classe que vous essayez de sérialisation et la désérialisation. En attendant, je vais faire une supposition.

Très probablement, le caractère non valide est dans un champ ou une propriété de type string. Vous aurez besoin de sérialisation que comme un tableau d'octets, en supposant que ne peut éviter d'avoir ce caractère présent à tous:

[XmlRoot("root")] 
public class HasBase64Content 
{ 
    internal HasBase64Content() 
    { 
    } 

    [XmlIgnore] 
    public string Content { get; set; } 

    [XmlElement] 
    public byte[] Base64Content 
    { 
     get 
     { 
      return System.Text.Encoding.UTF8.GetBytes(Content); 
     } 
     set 
     { 
      if (value == null) 
      { 
       Content = null; 
       return; 
      } 

      Content = System.Text.Encoding.UTF8.GetString(value); 
     } 
    } 
} 

Ce produit XML comme suit:

<?xml version="1.0" encoding="utf-8"?> 
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <Base64Content>AAECAwQFFA==</Base64Content> 
</root> 

I voyez-vous préféreriez probablement VB.NET:

''# Prettify doesn't like attributes as the first item in a VB code block, so this comment is here so that it looks right on StackOverflow. 
<XmlRoot("root")> _ 
Public Class HasBase64Content 

    Private _content As String 
    <XmlIgnore()> _ 
    Public Property Content() As String 
     Get 
      Return _content 
     End Get 
     Set(ByVal value As String) 
      _content = value 
     End Set 
    End Property 

    <XmlElement()> _ 
    Public Property Base64Content() As Byte() 
     Get 
      Return System.Text.Encoding.UTF8.GetBytes(Content) 
     End Get 
     Set(ByVal value As Byte()) 
      If Value Is Nothing Then 
       Content = Nothing 
       Return 
      End If 
      Content = System.Text.Encoding.UTF8.GetString(Value) 
     End Set 
    End Property 
End Class 
+0

Salut John. Le problème ici n'est pas de sérialiser un objet avec des caractères non valides. Le problème est pourquoi Xml.Serialization.XmlSerializer n'échappe pas aux caractères non valides lors de la sérialisation. – InfoStatus

+1

Selon ce qu'il sérialisait, il n'est probablement pas supposé y échapper. Il a besoin de montrer ce qu'il sérialise. –

+0

BTW, DK39, vérifiez mon profil. Je suis un peu expert dans ce domaine. Il ne s'agit pas d'échapper. –

6

Je mets t La propriété XmlReaderSettings CheckCharacters à false. Je vous conseille de le faire uniquement si vous avez sérialisé vous-même les données via XmlSerializer. Si c'est d'une source inconnue, ce n'est pas vraiment une bonne idée.

public static T Deserialize<T>(string xml) 
{ 
    var xmlReaderSettings = new XmlReaderSettings() { CheckCharacters = false }; 

    XmlReader xmlReader = XmlTextReader.Create(new StringReader(xml), xmlReaderSettings); 
    XmlSerializer xs = new XmlSerializer(typeof(T)); 

    return (T)xs.Deserialize(xmlReader); 
} 
+1

-1: n'utilisez pas XmlTextReader.Create. Utilisez 'XmlReader.Create'. –

+2

CheckCharacters = false est exactement ce dont j'avais besoin de savoir. Merci! –

+0

Super! Cela fonctionne finalement. Vous pouvez également passer XmlReaderSettings à XmlSerializer. C'est ce que je devais faire. – Jeremi

Questions connexes