XDocument.ToString () supprime la balise de codage XML

103

Existe-t-il un moyen d'obtenir le codage XML dans la fonction toString ()?

Exemple:

xml.Save("myfile.xml");

mène à

<?xml version="1.0" encoding="utf-8"?>
<Cooperations>
  <Cooperation>
    <CooperationId>xxx</CooperationId>
    <CooperationName>Allianz Konzern</CooperationName>
    <LogicalCustomers>

Mais

tb_output.Text = xml.toString();

conduit à une sortie comme celle-ci

<Cooperations>
  <Cooperation>
    <CooperationId>xxx</CooperationId>
    <CooperationName>Allianz Konzern</CooperationName>
    <LogicalCustomers>
    ...
Henrik P. Hessel
la source

Réponses:

98

Soit écrivez explicitement la déclaration, soit utilisez un StringWriteret appelez Save():

using System;
using System.IO;
using System.Text;
using System.Xml.Linq;

class Test
{
    static void Main()
    {
        string xml = @"<?xml version='1.0' encoding='utf-8'?>
<Cooperations>
  <Cooperation />
</Cooperations>";

        XDocument doc = XDocument.Parse(xml);
        StringBuilder builder = new StringBuilder();
        using (TextWriter writer = new StringWriter(builder))
        {
            doc.Save(writer);
        }
        Console.WriteLine(builder);
    }
}

Vous pouvez facilement ajouter cela comme méthode d'extension:

public static string ToStringWithDeclaration(this XDocument doc)
{
    if (doc == null)
    {
        throw new ArgumentNullException("doc");
    }
    StringBuilder builder = new StringBuilder();
    using (TextWriter writer = new StringWriter(builder))
    {
        doc.Save(writer);
    }
    return builder.ToString();
}

Cela a l'avantage que cela ne fonctionnera pas s'il n'y a pas de déclaration :)

Ensuite, vous pouvez utiliser:

string x = doc.ToStringWithDeclaration();

Notez que cela utilisera utf-16 comme encodage, car c'est l'encodage implicite dans StringWriter. Vous pouvez cependant influencer cela vous-même en créant une sous-classe de StringWriter, par exemple pour toujours utiliser UTF-8 .

Jon Skeet
la source
14
Cela a un petit problème en ce que l'encodage dans la déclaration XDocument est ignoré et remplacé par l'encodage de StringWriter lors de la sauvegarde, ce qui peut ou non être ce que vous voulez
Sam Holder
2
Ensuite, vous combinez la méthode d'extension avec: Utf8StringWriter de stackoverflow.com/a/1564727/75963 ;)
Nick Josevski
12
J'ai trouvé plus facile d'utiliser la méthode d'extension ci-dessus mais renvoyer ce qui suit ... return doc.Declaration + doc.ToString (); Si la déclaration est nulle, il en résulte simplement une chaîne vide.
Steve G.
Étrange, mais je ne peux pas le faire fonctionner maintenant ( .net fiddle ) - il utilise toujours l'encodage "utf-16". J'ai regardé à l'intérieur de l' XDocument.Save(TextWriter)implémentation et il ignore simplement le codage de la déclaration, par opposition aux implémentations XDocument.Save(String)ou XDocument.Save(Stream). Je me demande pourquoi ...
Ilya Luzyanin
@IlyaLuzyanin: Oui, il utilisera "utf-16" comme encodage lorsque vous passerez dans a StringWriter, sauf si vous en utilisez un qui remplace la Encodingpropriété. J'ai une autre réponse à ce sujet. Je pensais que vous disiez qu'il abandonnait entièrement "l'encodage" ...
Jon Skeet
46

La propriété Declaration contiendra la déclaration XML. Pour obtenir le contenu plus la déclaration, vous pouvez effectuer les opérations suivantes:

tb_output.Text = xml.Declaration.ToString() + xml.ToString()
Ryan Brunner
la source
7
il semble que si vous n'utilisez pas la nouvelle déclaration X ("1.0", "utf-8", "oui") dans votre xdocument, cela crée une erreur car xml.Declaration est nul. Mais xml.save semble détecter automatiquement le bon encodage.
Henrik P. Hessel
ou,tb_output.Text = @"<?xml version=""1.0"" encoding=""utf-8"" ?>" + xml;
Bill Hoag
4
ou... = $"{xdoc.Declaration}{Environment.NewLine}{xdoc}";
WernerCD
9

utilisez ceci:

output.Text = String.Concat(xml.Declaration.ToString() , xml.ToString())
Farooq Kaiser
la source
2
Sans créer de nouveau XDeclaration ("1.0", "utf-8", "yes") et ajouter dans XDocument ou un autre objet, xml.Declaration.ToString () lèvera une exception null.
Ziggler
1
c'est plus sûr comme ci-dessous car Concat ne se soucie pas des chaînes nulles: output.Text = String.Concat (xml.Declaration, xml)
dmihailescu
3

J'ai aimé ça

        string distributorInfo = string.Empty;

        XDocument distributors = new XDocument();

     //below is important else distributors.Declaration.ToString() throws null exception
        distributors.Declaration = new XDeclaration("1.0", "utf-8", "yes"); 

        XElement rootElement = new XElement("Distributors");
        XElement distributor = null;
        XAttribute id = null;

        distributor = new XElement("Distributor");
        id = new XAttribute("Id", "12345678");
        distributor.Add(id);
        rootElement.Add(distributor);

        distributor = new XElement("Distributor");
        id = new XAttribute("Id", "22222222");

        distributor.Add(id);

        rootElement.Add(distributor);         

        distributors.Add(rootElement);

        distributorInfo = String.Concat(distributors.Declaration.ToString(), distributors.ToString());

Veuillez voir ci-dessous ce que j'obtiens dans le distributeur

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Distributors>
  <Distributor Id="12345678" />
  <Distributor Id="22222222" />
  <Distributor Id="11111111" />
</Distributors>
Ziggler
la source
1
bon exemple. quelques notes: 1) utiliser la nouvelle déclaration X ("1.0", "utf-8") au lieu de la nouvelle déclaration X ("1.0", "utf-8", "oui"), 2) insérer une nouvelle ligne dans la dernière ligne: distributeurs. Declaration.ToString () + Environment.NewLine + distributeurs.ToString ()
Alexey Obukhov
2

Similaire aux autres réponses +1, mais un peu plus de détails sur la déclaration et une concaténation légèrement plus précise.

<xml />La déclaration doit être sur sa propre ligne dans un XML formaté, donc je m'assure que nous avons ajouté la nouvelle ligne. REMARQUE: en utilisant Environment.Newlineainsi, il produira la nouvelle ligne spécifique à la plate-forme

// Parse xml declaration menthod
XDocument document1 =
  XDocument.Parse(@"<?xml version=""1.0"" encoding=""iso-8859-1""?><rss version=""2.0""></rss>");
string result1 =
  document1.Declaration.ToString() +
  Environment.NewLine +
  document1.ToString() ;

// Declare xml declaration method
XDocument document2 = 
  XDocument.Parse(@"<rss version=""2.0""></rss>");
document2.Declaration =
  new XDeclaration("1.0", "iso-8859-1", null);
string result2 =
  document2.Declaration.ToString() +
  Environment.NewLine +
  document2.ToString() ;

Les deux résultats produisent:

<?xml version="1.0" encoding="iso-8859-1"?>
<rss version="2.0"></rss>
sonjz
la source
1

Certaines de ces réponses répondent à la demande de l'affiche, mais semblent trop compliquées. Voici une méthode d'extension simple qui évite le besoin d'un rédacteur séparé, gère une déclaration manquante et prend en charge le paramètre standard ToString SaveOptions.

public static string ToXmlString(this XDocument xdoc, SaveOptions options = SaveOptions.None)
{
    var newLine =  (options & SaveOptions.DisableFormatting) == SaveOptions.DisableFormatting ? "" : Environment.NewLine;
    return xdoc.Declaration == null ? xdoc.ToString(options) : xdoc.Declaration + newLine + xdoc.ToString(options);
}

Pour utiliser l'extension, remplacez simplement xml.ToString()parxml.ToXmlString()

B2K
la source
0

Vous pouvez également utiliser un XmlWriter et appeler le

Writer.WriteDocType() 

méthode.

Gus Paul
la source
0
string uploadCode = "UploadCode";
string LabName = "LabName";
XElement root = new XElement("TestLabs");
foreach (var item in returnList)
{  
       root.Add(new XElement("TestLab",
                new XElement(uploadCode, item.UploadCode),
                new XElement(LabName, item.LabName)
                            )
               );
}

XDocument returnXML = new XDocument(new XDeclaration("1.0", "UTF-8","yes"),
             root);

string returnVal;
using (var sw = new MemoryStream())
{
       using (var strw = new StreamWriter(sw, System.Text.UTF8Encoding.UTF8))
       {
              returnXML.Save(strw);
              returnVal = System.Text.UTF8Encoding.UTF8.GetString(sw.ToArray());
       }
}

// ReturnVal has the string with XML data with XML declaration tag
David
la source