通过 XmlWriter 写入默认 xmlns 属性的自定义缩进

Custom indent for default xmlns attribute wile writing through XmlWriter

我正在努力寻找使用 XmlWriter 和基础字符串生成器准确编写此 XML 的适当方法:

<x:node xmlns="uri:default"
        xmlns:x="uri:special-x"
        xmlns:y="uri:special-y"
        y:name="MyNode"
        SomeOtherAttr="ok">
</x:node>

我目前最好的:

static string GetXml()
{
    var r = new StringBuilder();
    var w = XmlWriter.Create(r, new XmlWriterSettings { OmitXmlDeclaration = true });
    w.WriteStartElement("x", "node", "uri:special-x");
    w.Flush();
    r.Append("\n" + new string(' ', 7));
    w.WriteAttributeString("xmlns", "x", null, "uri:special-x");
    w.Flush();
    r.Append("\n" + new string(' ', 7));
    w.WriteAttributeString("xmlns", "y", null, "uri:special-y");
    w.Flush();
    r.Append("\n" + new string(' ', 7));
    w.WriteAttributeString("name", "uri:special-y", "vd");
    w.Flush();
    r.Append("\n" + new string(' ', 7));
    w.WriteAttributeString("SomeOtherAttr", "ok");
    w.Flush();
    w.WriteEndElement();
    w.Flush();
    return r.ToString();
}

这创造了

<x:node
        xmlns:x="uri:special-x"
        xmlns:y="uri:special-y"
        y:name="vd"
        SomeOtherAttr="ok" />

但我找不到在节点之后立即编写默认 xmlns 的方法。任何尝试都会导致错误或格式不同。

有什么想法吗?谢谢!

更新:也许我可以将其直接写入 StringBuilder,但我正在寻找更多...嗯...正确的方法。

您需要实际添加您的默认名称空间,而您目前没有这样做:

var sb = new StringBuilder();
var writer = XmlWriter.Create(sb, new XmlWriterSettings
{
    OmitXmlDeclaration = true,
});

using (writer)
{
    writer.WriteStartElement("x", "node", "uri:special-x");
    writer.WriteAttributeString("xmlns", "uri:default");
    writer.Flush();
    sb.Append("\n" + new string(' ', 7));
    writer.WriteAttributeString("xmlns", "x", null, "uri:special-x");
    writer.Flush();
    sb.Append("\n" + new string(' ', 7));
    writer.WriteAttributeString("xmlns", "y", null, "uri:special-y");
    writer.Flush();
    sb.Append("\n" + new string(' ', 7));
    writer.WriteAttributeString("name", "uri:special-y", "vd");
    writer.Flush();
    sb.Append("\n" + new string(' ', 7));
    writer.WriteAttributeString("SomeOtherAttr", "ok");            
    writer.WriteEndElement();
}  

查看此演示:https://dotnetfiddle.net/994YqW

话虽这么说,你为什么要这样做?让它按照自己喜欢的方式格式化,它在语义上仍然相同并且完全有效。

为什么这么难? 请试试这个:

var r = new StringBuilder();

var settings = new XmlWriterSettings
{
    OmitXmlDeclaration = true,
    NewLineOnAttributes = true,
    Indent = true,
    IndentChars = "\t"
};

using (var w = XmlWriter.Create(r, settings))
{
    w.WriteStartElement("x", "node", "uri:special-x");

    w.WriteAttributeString("xmlns", "x", null, "uri:special-x");
    w.WriteAttributeString("xmlns", "y", null, "uri:special-y");
    w.WriteAttributeString("name", "uri:special-y", "vd");
    w.WriteAttributeString("SomeOtherAttr", "ok");

    w.WriteEndElement();
}

所有命名空间都在一行上。