XDocument.ToString () скидає тег кодування XML


103

Чи є спосіб отримати кодування xml у функції toString ()?

Приклад:

xml.Save("myfile.xml");

призводить до

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

Але

tb_output.Text = xml.toString();

призводить до такого виходу

<Cooperations>
  <Cooperation>
    <CooperationId>xxx</CooperationId>
    <CooperationName>Allianz Konzern</CooperationName>
    <LogicalCustomers>
    ...

Відповіді:


98

Або явно випишіть декларацію, або використовуйте StringWriterі виклик 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);
    }
}

Ви можете легко додати це як метод розширення:

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

Це має перевагу в тому, що він не буде тремтіти, якщо не буде декларації :)

Тоді ви можете використовувати:

string x = doc.ToStringWithDeclaration();

Зауважте, що це використовуватиме utf-16 як кодування, оскільки це неявне кодування в StringWriter. Ви можете самі на це вплинути, створивши підклас StringWriter, наприклад, завжди використовувати UTF-8 .


14
У цьому є невелика проблема в тому, що кодування в декларації XDocument ігнорується і замінюється кодуванням StringWriter під час збереження, яке може бути, а може і не бути тим, що ви хочете
Сем Холдер

2
Тоді ви поєднуєте метод розширення з: Utf8StringWriter з stackoverflow.com/a/1564727/75963 ;)
Нік Josevski

12
Вище було простіше використовувати метод розширення, але повернути наступне ... return doc.Declaration + doc.ToString (); Якщо Декларація є нульовою, це просто призводить до порожнього рядка.
Стів Г.

Дивно, але я не можу змусити його працювати зараз ( .net fiddle ) - він завжди використовує кодування "utf-16". Я переглянув внутрішню XDocument.Save(TextWriter)реалізацію, і вона просто ігнорує кодування декларації, на відміну від XDocument.Save(String)або XDocument.Save(Stream)реалізації. Цікаво, чому ...
Ілля Лузянін

@IlyaLuzyanin: Так, він буде використовувати "utf-16" в якості кодування при переході в a StringWriter, якщо ви не використовуєте той, що перекриває Encodingвластивість. У мене є ще одна відповідь з цього приводу. Я думав, ти кажеш, що повністю скидаєш "кодування" ...
Джон Скіт

46

Властивість Declaration буде містити декларацію XML. Щоб отримати вміст плюс декларацію, ви можете зробити наступне:

tb_output.Text = xml.Declaration.ToString() + xml.ToString()

7
здається, якщо ви не використовуєте нову XDeclaration ("1.0", "utf-8", "так") у своєму xdocument, це створює помилку, оскільки xml.Declaration є недійсною. Але xml.save, здається, автоматично виявляє правильне кодування.
Генрік П. Гессел

або,tb_output.Text = @"<?xml version=""1.0"" encoding=""utf-8"" ?>" + xml;
Білл Хоґ

4
або... = $"{xdoc.Declaration}{Environment.NewLine}{xdoc}";
WernerCD

9

використовуй це:

output.Text = String.Concat(xml.Declaration.ToString() , xml.ToString())

2
Без створення нового XDeclaration ("1.0", "utf-8", "так") і додавання в XDocument або інший об'єкт, xml.Declaration.ToString () викине нульовий виняток.
Ziggler

1
Це безпечніше, як нижче, оскільки Concat не піклується про нульові рядки: output.Text = String.Concat (xml.Declaration, xml)
dmihailescu

3

Мені це подобалось

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

Будь ласка, дивіться нижче, що я отримую у дистриб'ютораInfo

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Distributors>
  <Distributor Id="12345678" />
  <Distributor Id="22222222" />
  <Distributor Id="11111111" />
</Distributors>

1
хороший приклад. деякі примітки: 1) використовувати нову XDeclaration ("1.0", "utf-8") замість нової XDeclaration ("1.0", "utf-8", "так"), 2) вставити новий рядок в останній рядок: розповсюджувачі. Декларація.ToString () + Environment.NewLine + дистриб'ютори.ToString ()
Олексій Обухов

2

Подібно до інших відповідей +1, але трохи детальніше про декларацію та дещо точніше з'єднання.

<xml />декларація повинна бути у власному рядку у форматованому XML, тому я переконуюсь, що у нас доданий новий рядок. ПРИМІТКА: використовуючи Environment.Newlineтак, це створить конкретний для платформи новий рядок

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

Обидва результати дають:

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

1

Кілька з цих відповідей вирішують запит афіші, але здаються надмірно складними. Ось простий метод розширення, який дозволяє уникнути потреби в окремому записувачі, обробляє відсутню декларацію та підтримує стандартний параметр 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);
}

Щоб використовувати розширення, просто замініть xml.ToString()наxml.ToXmlString()


0

Ви також можете використовувати XmlWriter і зателефонувати на

Writer.WriteDocType() 

метод.


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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.