XmlWriter вставка пробелов при xml: space = preserve - PullRequest
4 голосов
/ 10 августа 2011

Учитывая этот код (C #, .NET 3.5 SP1):

var doc = new XmlDocument();
doc.LoadXml("<?xml version=\"1.0\"?><root>"
    + "<value xml:space=\"preserve\">"
    + "<item>content</item>"
    + "<item>content</item>"
    + "</value></root>");

var text = new StringWriter();
var settings = new XmlWriterSettings() { Indent = true, CloseOutput = true };
using (var writer = XmlWriter.Create(text, settings))
{
    doc.DocumentElement.WriteTo(writer);
}

var xml = text.GetStringBuilder().ToString();
Assert.AreEqual("<?xml version=\"1.0\" encoding=\"utf-16\"?>\r\n<root>\r\n"
    + "  <value xml:space=\"preserve\"><item>content</item>"
    + "<item>content</item></value>\r\n</root>", xml);

Утверждение не выполняется, поскольку XmlWriter вставляет символ новой строки и отступ вокруг элементов <item>, что может показаться противоречащиматрибут xml:space="preserve".

Я пытаюсь получить ввод без пробелов (или только значительных пробелов, уже загруженных в XmlDocument) и красиво распечатать его без , добавив любыеПробелы внутри элементов, помеченных для сохранения пробелов (по понятным причинам).

Это ошибка или я что-то не так делаю?Есть ли лучший способ добиться того, что я пытаюсь сделать?

Редактировать : Вероятно, я должен добавить, что мне нужно использовать XmlWriter с Indent=true на выходебоковая сторона.В «реальном» коде это передается извне моего кода.

1 Ответ

4 голосов
/ 11 августа 2011

Хорошо, я нашел обходной путь.

Оказывается, что XmlWriter делает правильные вещи, если на самом деле равен любому пробелу в блоке xml:space="preserve" - только когда его нет, он облажается и добавляет некоторые. И удобно, это также работает, если есть некоторые пробельные узлы, даже если они пусты. Итак, хитрость, которую я придумала, состоит в том, чтобы украсить документ дополнительными пробелами нулевой длины в соответствующих местах, прежде чем пытаться выписать его. Результат - именно то, что я хочу: красивая печать везде, кроме тех случаев, когда пробелы значительны.

Обходной путь должен изменить внутренний блок на:

PreserveWhitespace(doc.DocumentElement);
doc.DocumentElement.WriteTo(writer);

...

private static void PreserveWhitespace(XmlElement root)
{
    var nsmgr = new XmlNamespaceManager(root.OwnerDocument.NameTable);
    foreach (var element in root.SelectNodes("//*[@xml:space='preserve']", nsmgr)
        .OfType<XmlElement>())
    {
        if (element.HasChildNodes && !(element.FirstChild is XmlSignificantWhitespace))
        {
            var whitespace = element.OwnerDocument.CreateSignificantWhitespace("");
            element.InsertBefore(whitespace, element.FirstChild);
        }
    }
}

Я все еще думаю, что такое поведение XmlWriter, однако, является ошибкой.

...