【发布时间】:2019-08-11 12:40:26
【问题描述】:
XmlWriter 允许在使用XmlWriter.Create 和XmlWriterSettings 时配置缩进。
一般来说,我想要Indent = true 和NewLineOnAttributes = false,except 在文件开头写xmlns 命名空间声明时,我想在每个@987654329 之间有新行@命名空间以提高可读性。
是否可以在写入特定属性后强制XmlWriter进行换行,否则遵循一般缩进规则?
我尝试将WriteWhitespace 和WriteRaw 与\n 一起使用:
using System;
using System.Text;
using System.Xml;
namespace XmlWriterIndent
{
class Program
{
static void Main(string[] args)
{
var output = new StringBuilder();
using (var writer = XmlWriter.Create(output, new XmlWriterSettings { Indent = true, NewLineOnAttributes = true }))
{
writer.WriteStartDocument();
writer.WriteStartElement("Node");
writer.WriteAttributeString("key1", "value1");
writer.WriteAttributeString("key2", "value2");
writer.WriteAttributeString("xmlns", "n1", null, "scheme://mynamespace.com");
writer.WriteRaw("\n");
writer.WriteAttributeString("xmlns", "n2", null, "scheme://anothernamespace.com");
writer.WriteEndElement();
writer.WriteEndDocument();
}
var xml = output.ToString();
Console.WriteLine(xml);
}
}
}
不幸的是,这会引发异常,说明 XML 文档无效。
更新:实际上,经过仔细检查,异常不在WriteRaw方法本身,而是在下面的WriteAttributeString调用中,因为我在循环中调用这些方法适用于所有命名空间。
看起来WriteRaw 以某种方式将XmlWriter 移动到元素内容状态。是否可以使用WriteRaw 或以某种方式在属性之间插入空格而不更改编写器状态?
更新:添加了独立的示例。实际上,即使使用NewLineOnAttributes,通常也会忽略命名空间声明,即所有属性都有新的行except命名空间声明,尽管是常规属性,但它们的处理方式有所不同。
不幸的是,我得出的结论是,XmlWriter API 完全被破坏了,因为无法对 XML 进行原始格式设置,因为WriteRaw 会强制更改写入器状态。
在参考源查看实际源代码表明,特殊的写入方法WriteIndent 用于处理XmlWriter 内部的缩进。此方法具有不会更改状态的特殊行为,但似乎无法访问它或底层数据流,因此如果不完全重新实现整个 XML 编写器堆栈,似乎不可能解决此问题:
https://referencesource.microsoft.com/#System.Xml/System/Xml/Core/XmlEncodedRawTextWriter.cs,1739
【问题讨论】:
-
您能否仅在使用 XML 命名空间编写元素/属性期间启用
NewLineOnAttributes? -
在编写命名空间后设置 NewLineOnAttributes = false。
-
很遗憾,在创建
XmlWriter后无法更改XmlWriterSettings属性。出于某种原因,它们被标记为只读,如果您尝试更改任何内容,框架将抛出异常。 -
@glopes 请编辑您的问题以包含您作为minimal reproducible example 的完整源代码,其他人可以编译和测试。包括您为在 XML 元素中添加新行所做的所有尝试,并添加您从中获得的错误消息和结果。特别是在您的尝试中包含完整的异常消息。
-
我添加了最小可重现示例,并进一步了解 API 和观察到的行为。我不认为异常消息会添加任何进一步的信息,无论如何谁想看到它只需要运行程序即可。