5

このコード (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で withを使用する必要があることを追加する必要があります。Indent=true「実際の」コードでは、これは私のコードの外から渡されています。

4

1 に答える 1

5

わかりました、回避策を見つけました。

実際にブロック内に空白あれば、それXmlWriterは正しいことをすることがわかりました- それが台無しになっていくつかを追加するのは何もないときだけです。便利なことに、空白ノードが空であっても、これはいくつかの空白ノードがある場合にも機能します。したがって、私が思いついたトリックは、文書を書き出す前に、適切な場所に長さ 0 の余分な空白を追加して文書を装飾することです。結果はまさに私が望んでいたものです。空白が重要な場所を除いて、どこでもきれいに印刷されます。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はバグだとまだ考えています。

于 2011-08-11T06:55:27.487 に答える