Где моя XDeclaration?

По какой-то причине следующий код создает XML, который не содержит объявления:

        XDocument xDocument = new XDocument(new XDeclaration("1.0", "utf-8", "yes"),
            new XElement("project",
                new XAttribute("number", project.ProjectNumber),
                new XElement("store",
                    new XAttribute("number", project.StoreNumber)
                ),

                // User Element
                new XElement("user", 
                    new XAttribute("owner-id", project.OwnerID ?? 0),
                    new XElement("email", new XCData(project.OwnerEmail ?? "")),
                    new XElement("project-name", new XCData(project.ProjectName ?? ""))
                ),

                // Nested Project Element
                new XElement("nested-project", 
                    new XAttribute("version", new Version(1, 0)),
                    new XElement("project", 
                        new XAttribute("version", new Version(1, 0)),
                        xProjectItems = new XElement("project-items")
                    ),
                    new XElement("price-per-part", project.PricePerPart),
                    new XElement("sheet-quantity", project.SheetQuantity),
                    new XElement("edge-length", project.EdgeLength),
                    new XElement("price", project.Price),
                    new XElement("status", project.Status),
                    xMaterialItems = new XElement("alternative-material-items"),
                    xProductItems = new XElement("project-product-items")
                )
            )
        );

        String strXML = xDocument.ToString();

Он сделал выражение раньше. Мне что-то не хватает?

Спасибо.

Ответы

Ответ 1

XDeclaration будет доступен, если вы используете один из методов XDocument.Save. Например:

var doc = new XDocument (
            new XDeclaration ("1.0", "utf-8", "yes"),
            new XElement ("test", "data")
        );

string path = Path.Combine(Path.GetTempPath(), "temp.xml");
doc.Save(path);
Console.WriteLine(File.ReadAllText(path));

Альтернативно вы можете использовать этот подход:

var sw = new StringWriter();
doc.Save(sw);
string result = sw.GetStringBuilder().ToString();
Console.WriteLine(result);

EDIT: обратите внимание, что некоторые подходы преобразуют обозначение utf-8 в utf-16. Если вы хотите заставить его быть utf-8, вам придется использовать этот другой подход:

using (var mem = new MemoryStream())  
using (var writer = new XmlTextWriter(mem, System.Text.Encoding.UTF8))
{
    writer.Formatting = Formatting.Indented;
    doc.WriteTo(writer);
    writer.Flush();
    mem.Flush();
    mem.Seek(0, SeekOrigin.Begin);
    using (var reader = new StreamReader(mem))
    {
        var xml = reader.ReadToEnd();
        Console.WriteLine(xml);
    }
}

Ответ 2

Документация не указывает явно, что xDocument.ToString() выводит объявление XML, оно только говорит: "Возвращает отступы XML для этого node"..

В моем тестировании я обнаружил, что следующие методы выдадут объявление:

Используйте ToString в свойстве Declaration:

string strXML = string.Concat(xDocument.Declaration.ToString(), "\r\n",
                              xDocument.ToString());

или используйте метод Save:

string strXml;
using(var ms = new MemoryStream())
{
    xDocument.Save(ms);
    ms.Position = 0;
    using(var sr = new StreamReader(ms))
    {
        strXml = sr.ReadToEnd();
    }
}

Ответ 3

Мой ответ (вдохновленный ответом @rsbarro):

string xml = xDocument.Declaration.ToString() +
    xDocument.ToString();

- или -

string xml = xDocument.Declaration.ToString() +
    xDocument.ToString(SaveOptions.DisableFormatting);

Что касается того, почему я полагаю, что использование оператора + является подходящим в этой ситуации, см. этот ответ на вопрос Какой лучший метод конкатенации строк с использованием С#?.