XDocument.ToString () löscht das XML-Codierungs-Tag

103

Gibt es eine Möglichkeit, die XML-Codierung in der Funktion toString () abzurufen?

Beispiel:

xml.Save("myfile.xml");

führt zu

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

Aber

tb_output.Text = xml.toString();

führt zu einer solchen Ausgabe

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

Antworten:

98

Schreiben Sie die Deklaration entweder explizit aus oder verwenden Sie a StringWriterund call 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);
    }
}

Sie können dies leicht als Erweiterungsmethode hinzufügen:

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();
}

Dies hat den Vorteil, dass es nicht knallt, wenn es keine Erklärung gibt :)

Dann können Sie verwenden:

string x = doc.ToStringWithDeclaration();

Beachten Sie, dass dabei utf-16 als Codierung verwendet wird, da dies die implizite Codierung in ist StringWriter. Sie können dies jedoch selbst beeinflussen, indem Sie eine Unterklasse von erstellen StringWriter, z. B. um immer UTF-8 zu verwenden .

Jon Skeet
quelle
14
Dies hat ein kleines Problem, da die Codierung in der XDocument-Deklaration ignoriert und beim Speichern durch die Codierung des StringWriter ersetzt wird, was möglicherweise das ist, was Sie wollen
Sam Holder,
2
Dann kombinieren Sie die Erweiterungsmethode mit: Utf8StringWriter von stackoverflow.com/a/1564727/75963 ;)
Nick Josevski
12
Fand es einfacher, die obige Erweiterungsmethode zu verwenden, gab aber Folgendes zurück ... return doc.Declaration + doc.ToString (); Wenn die Deklaration null ist, führt dies nur zu einer leeren Zeichenfolge.
Steve G.
Seltsam, aber ich kann es jetzt nicht zum Laufen bringen ( .net-Geige ) - es verwendet immer die "utf-16" -Codierung. Ich habe mir die XDocument.Save(TextWriter)Implementierung angesehen und sie ignoriert nur die Codierung der Deklaration im Gegensatz zu XDocument.Save(String)oder XDocument.Save(Stream)Implementierungen. Ich frage mich warum ...
Ilya Luzyanin
@IlyaLuzyanin: Ja, es wird "utf-16" als Codierung verwendet, wenn Sie a übergeben StringWriter, es sei denn, Sie verwenden eine, die die EncodingEigenschaft überschreibt . Ich habe noch eine Antwort darauf. Ich dachte, Sie sagten, es würde die "Codierung" vollständig
löschen
46

Die Declaration-Eigenschaft enthält die XML-Deklaration. Um den Inhalt plus Deklaration zu erhalten, können Sie Folgendes tun:

tb_output.Text = xml.Declaration.ToString() + xml.ToString()
Ryan Brunner
quelle
7
Wenn Sie in Ihrem xdocument keine neue XDeclaration ("1.0", "utf-8", "yes") verwenden, wird anscheinend ein Fehler erstellt, da xml.Declaration null ist. Aber xml.save scheint die richtige Codierung automatisch zu erkennen.
Henrik P. Hessel
odertb_output.Text = @"<?xml version=""1.0"" encoding=""utf-8"" ?>" + xml;
Bill Hoag
4
oder... = $"{xdoc.Declaration}{Environment.NewLine}{xdoc}";
WernerCD
9

benutze das:

output.Text = String.Concat(xml.Declaration.ToString() , xml.ToString())
Farooq Kaiser
quelle
2
Ohne eine neue XDeclaration ("1.0", "utf-8", "yes") zu erstellen und in XDocument oder ein anderes Objekt hinzuzufügen, löst xml.Declaration.ToString () eine Null-Ausnahme aus.
Ziggler
1
Es ist sicherer wie unten, weil Concat sich nicht um Null-Strings kümmert: output.Text = String.Concat (xml.Declaration, xml)
dmihailescu
3

Das hat mir gefallen

        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());

Bitte sehen Sie unten, was ich in DistributorInfo bekomme

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Distributors>
  <Distributor Id="12345678" />
  <Distributor Id="22222222" />
  <Distributor Id="11111111" />
</Distributors>
Ziggler
quelle
1
gutes Beispiel. Einige Hinweise: 1) Verwenden Sie eine neue XDeclaration ("1.0", "utf-8") anstelle einer neuen XDeclaration ("1.0", "utf-8", "yes"). 2) Fügen Sie eine neue Zeile in die letzte Zeile ein: Verteiler. Declaration.ToString () + Environment.NewLine + Distributoren.ToString ()
Alexey Obukhov
2

Ähnlich wie bei den anderen +1 Antworten, jedoch etwas detaillierter über die Deklaration und eine etwas genauere Verkettung.

<xml />Die Deklaration sollte in einem formatierten XML in einer eigenen Zeile stehen, daher stelle ich sicher, dass die neue Zeile hinzugefügt wurde. HINWEIS: Environment.NewlineWenn Sie dies verwenden, wird die plattformspezifische Newline erstellt

// 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() ;

Beide Ergebnisse ergeben:

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

Einige dieser Antworten lösen die Anfrage des Posters, scheinen jedoch zu kompliziert zu sein. Hier ist eine einfache Erweiterungsmethode, die die Notwendigkeit eines separaten Writers vermeidet, eine fehlende Deklaration behandelt und den Standardparameter ToString SaveOptions unterstützt.

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);
}

Um die Erweiterung zu verwenden, ersetzen Sie einfach xml.ToString()mitxml.ToXmlString()

B2K
quelle
0

Sie können auch einen XmlWriter verwenden und den aufrufen

Writer.WriteDocType() 

Methode.

Gus Paul
quelle
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
quelle