XDocument.ToString () menjatuhkan Tag Pengkodean XML

103

Apakah ada cara untuk mendapatkan pengkodean xml di Fungsi toString ()?

Contoh:

xml.Save("myfile.xml");

mengarah ke

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

Tapi

tb_output.Text = xml.toString();

mengarah ke keluaran seperti ini

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

Jawaban:

98

Tuliskan deklarasi secara eksplisit, atau gunakan StringWriterdan panggil 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);
    }
}

Anda dapat dengan mudah menambahkannya sebagai metode ekstensi:

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

Ini memiliki keuntungan bahwa tidak akan meledak jika tidak ada deklarasi :)

Kemudian Anda dapat menggunakan:

string x = doc.ToStringWithDeclaration();

Perhatikan bahwa itu akan menggunakan utf-16 sebagai pengkodean, karena itulah pengkodean implisit dalam StringWriter. Anda dapat memengaruhinya sendiri dengan membuat subkelas StringWriter, misalnya, untuk selalu menggunakan UTF-8 .

Jon Skeet
sumber
14
Ini memiliki masalah kecil di mana pengkodean dalam deklarasi XDocument diabaikan dan diganti dengan pengkodean StringWriter saat melakukan penyimpanan, yang mungkin atau mungkin bukan yang Anda inginkan
Sam Holder
2
Kemudian Anda menggabungkan metode ekstensi dengan: Utf8StringWriter dari stackoverflow.com/a/1564727/75963 ;)
Nick Josevski
12
Merasa lebih mudah menggunakan metode ekstensi di atas tetapi mengembalikan yang berikut ... return doc.Declaration + doc.ToString (); Jika Deklarasi null, itu hanya menghasilkan string kosong.
Steve G.
Aneh, tapi saya tidak bisa membuatnya berfungsi sekarang ( biola .net ) - selalu menggunakan pengkodean "utf-16". Saya telah melihat ke dalam XDocument.Save(TextWriter)implementasi dan itu hanya mengabaikan pengkodean deklarasi, sebagai lawan XDocument.Save(String)atau XDocument.Save(Stream)implementasi. Aku bertanya-tanya mengapa ...
Ilya Luzyanin
@IlyaLuzyanin: Ya, ini akan menggunakan "utf-16" sebagai pengkodean ketika Anda meneruskan StringWriter, kecuali jika Anda menggunakan salah satu yang menimpa Encodingproperti. Saya punya jawaban lain tentang itu. Saya pikir Anda mengatakan itu menjatuhkan "pengkodean" seluruhnya ...
Jon Skeet
46

Properti Deklarasi akan berisi deklarasi XML. Untuk mendapatkan deklarasi konten plus, Anda dapat melakukan hal berikut:

tb_output.Text = xml.Declaration.ToString() + xml.ToString()
Ryan Brunner
sumber
7
tampaknya jika Anda tidak menggunakan XDeclaration baru ("1.0", "utf-8", "yes") di xdocument Anda, ini akan membuat kesalahan karena xml.Declaration adalah null. Tetapi xml.save tampaknya mendeteksi secara otomatis pengkodean yang benar.
Henrik P. Hessel
atau,tb_output.Text = @"<?xml version=""1.0"" encoding=""utf-8"" ?>" + xml;
Bill Hoag
4
atau... = $"{xdoc.Declaration}{Environment.NewLine}{xdoc}";
WernerCD
9

Gunakan ini:

output.Text = String.Concat(xml.Declaration.ToString() , xml.ToString())
Farooq Kaiser
sumber
2
Tanpa membuat XDeclaration baru ("1.0", "utf-8", "yes") dan menambahkan ke XDocument atau objek lain, xml.Declaration.ToString () akan melontarkan pengecualian null.
Ziggler
1
lebih aman seperti di bawah ini karena Concat tidak peduli dengan string null: output.Text = String.Concat (xml.Declaration, xml)
dmihailescu
3

Saya suka ini

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

Silakan lihat di bawah untuk apa yang saya dapatkan di distributorInfo

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Distributors>
  <Distributor Id="12345678" />
  <Distributor Id="22222222" />
  <Distributor Id="11111111" />
</Distributors>
Ziggler
sumber
1
contoh yang baik. beberapa catatan: 1) gunakan XDeclaration baru ("1.0", "utf-8") sebagai ganti XDeclaration baru ("1.0", "utf-8", "yes"), 2) masukkan baris baru di baris terakhir: distributor. Declaration.ToString () + Environment.NewLine + distributor.ToString ()
Alexey Obukhov
2

Mirip dengan jawaban +1 lainnya, tetapi sedikit lebih detail tentang deklarasi, dan penggabungan yang sedikit lebih akurat.

<xml />deklarasi harus berada di barisnya sendiri dalam format XML, jadi saya memastikan kita memiliki baris baru yang ditambahkan. CATATAN: menggunakan Environment.Newlinesehingga akan menghasilkan baris baru khusus platform

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

Kedua hasil tersebut menghasilkan:

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

Beberapa dari jawaban ini menyelesaikan permintaan poster, tetapi tampak terlalu rumit. Berikut adalah metode ekstensi sederhana yang menghindari kebutuhan akan penulis terpisah, menangani deklarasi yang hilang, dan mendukung parameter ToString SaveOptions standar.

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

Untuk menggunakan ekstensi, cukup ganti xml.ToString()denganxml.ToXmlString()

B2K
sumber
0

Anda juga dapat menggunakan XmlWriter dan memanggil file

Writer.WriteDocType() 

metode.

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