10
votes

Comment dois-je modifier cette chaîne XML afin que xdocument.parse le lit?

Dans le code suivant, je Serialize un objet dans une chaîne XML .

Mais quand j'essaie de lire cette chaîne XML dans un xdocument < / forte> avec xdocument.parse, cela me donne cette erreur :

Données non valides au niveau de la racine.

Le XML est: xxx

update: Voici l'hex:

! [ALT TEXT] [1] MOD EDIT - Liens hypertexte désactivé: Liens vers les logiciels malveillants

Que dois-je faire sur ce XML afin qu'il se lit dans le xdocument sans erreur? xxx

réponse:

merci Anras, GetPreamble (), donc pour que quiconque traite, donc pour toute autre affaire Avec cela, voici une petite méthode pour nettoyer votre XML de la naissance: xxx


5 commentaires

Il n'y a rien de mal avec ce xml. Êtes-vous sûr que c'est le même XML qui provoque l'exception?


Données non valides au niveau de la racine, ligne 1, caractère 1. Lorsque je copie le texte dans le bloc-notes ++, le premier caractère est un "?" Et dans d'autres éditeurs, certains personnages de contrôle ...


Ensuite, vous avez perdu l'ouverture "<" pendant la coupe et la pâte. Il n'y a rien de mal avec le XML.


C'est des marques d'ordre d'octets ou similaires - mais je ne reconnais pas celui-là!


Je pense avoir une solution plus élégante, jetez un coup d'œil à ma réponse.


3 Réponses :


15
votes

C'est parce que les données contiennent l'UNICODE ou UTF8 BOM Marks au début du flux.

Vous devez passer au-delà des marques d'ordre d'octets dans le flux - vous pouvez les identifier à partir du system.text.encoding.getPreamble () méthode.


5 commentaires

Vous obtenez souvent ce problème lors de la création de fichiers XML dans le Bloc-notes. VS peut aussi les ajouter parfois aussi.


Utiliser GettPreamble () est une tentative de résoudre les conséquences plutôt que de la raison. Regardez ma réponse s'il vous plaît.


Oui c'est une bonne réponse - et cela fonctionne, si le codage est toujours utf8. Cependant, en utilisant la méthode GetPreamble, vous pouvez détecter automatiquement le codage d'un fichier, ce qui signifie que vous n'êtes pas lié à un seul. Une fois sélectionné, vous pouvez ensuite ajuster votre échantillon de code pour accueillir tout encodage.


D'accord, mais pourquoi vous devriez avoir une solution plus complexe prévoyant de futurs codages qui ne pourraient jamais être nécessaires. Je ne le suggérais pas si vous n'avez besoin que de UTF8 pour le moment. Yagni.


Ce n'est vraiment pas si difficile ou cela compliqué, j'ai une méthode d'extension dans une bibliothèque de référence commune que j'utilise et qui est probablement environ 10-15 lignes de code. Je sais ce que vous dites, et je suis d'accord en principe, mais parfois la solution complète en vaut la peine, surtout si cela ne pose pas de complexité d'une grande quantité.



1
votes

Vous pouvez résoudre votre problème à l'aide d'un StreamReader code> pour convertir les données dans le code> MemoryStream code> à une chaîne à la place:

public static string SerializeObject<T>(object o)
{
    using (MemoryStream ms = new MemoryStream())
    {
        XmlSerializer xs = new XmlSerializer(typeof(T));
        using (XmlWriter xtw = XmlWriter.Create(ms))
        {
            xs.Serialize(xtw, o);
            xtw.Flush();
            ms.Seek(0, SeekOrigin.Begin);
            using (StreamReader reader = new StreamReader(ms))
            {
                return reader.ReadToEnd();
            }
        }
    }
}


2 commentaires

-1: xmltextwriter est obsolète. Utilisez xmlwriter.create à la place.


@John: Le compilateur Nume qu'aucune information sur xmltextwriter est obsolète. Je connais la recommandation xmlwriter.create , mais je ne voulais pas modifier le code OP plus que nécessaire pour résoudre le problème. Néanmoins, a mis à jour mon échantillon de code pour suivre la recommandation.



-1
votes

Tout ce qui précède est correct et voici un code que vous devez utiliser au lieu de la location pour sauter BOM: xxx

en spécifiant faux dans le constructeur que vous dites "BOM n'est pas fourni". Prendre plaisir! =)


2 commentaires

-1, -1, -1: Vous devez mettre à l'aide des blocs autour du Morthstream et le xmlwriter . Vous devez utiliser xmltextwriter , qui a été obsolète depuis .net 2.0 - Utilisez xmlwriter.create à la place. Le paramètre o doit être de type t ; Entre autres choses, cela permettrait à vos appelants de ne pas spécifier - il sera souvent impliqué par le type de paramètre.


D'accord, mais ceci est une copie du code d'origine avec une seule modification, ce n'est donc pas ma cible de l'examiner et de trouver des trous et des problèmes de conception. Si vous essayez de lire cette discussion, vous remarquerez probablement que j'ai résolu le problème que j'ai demandé. Alors prenez votre "-1" dehors, monsieur.