C# 删除XDocument.ToString()中空元素中的额外空间

C# 删除XDocument.ToString()中空元素中的额外空间,c#,linq-to-xml,C#,Linq To Xml,我正在向一个无法处理标记中空格的系统发送XML消息。值中的空格可以。我一直在使用linq/XDocument/XElements来操作/生成消息 问题是当元素为空时。例如: XDocument xdoc = XDocument.Parse("<root><value/></root>"); Console.WriteLine(xdoc.ToString(SaveOptions.DisableFormatting)); 所以我在上面贴了一个替代品: Conso

我正在向一个无法处理标记中空格的系统发送XML消息。值中的空格可以。我一直在使用linq/XDocument/XElements来操作/生成消息

问题是当元素为空时。例如:

XDocument xdoc = XDocument.Parse("<root><value/></root>");
Console.WriteLine(xdoc.ToString(SaveOptions.DisableFormatting));
所以我在上面贴了一个替代品:

Console.WriteLine(xdoc.ToString(SaveOptions.DisableFormatting).Replace(" />","/>"));

我在那里会遇到什么不好的事情吗?是否有一种明显的/更标准的方法来做到这一点?看起来JAG.< /P> < P>如果您的目标系统以与自关闭XML元素相同的方式处理空XML元素——一般来说,两者都被认为是相等的(但是请考虑下面的注释)——您可以实现一个自定义的<代码> XmlWriter < /C> >,它将自封的XML标签输出为空的XML标签。 空xml标记不会在其标记中包含任何空格,例如

下面示例中的自定义
XmlTextWriter
生成以下xml。
请注意
标记以及
值WithWhitespace
的空白值已被保留

<root><value></value><valueWithWhitespace>   </valueWithWhitespace></root>

如果您对额外的缓冲(使用String.Replace,看起来是这样的),也可以用另一种方式完成:

然后您可以将其从内存流中取出。stringreplace的不同之处在于,这种方法不会破坏像CDATA节这样的内容。使用完全结束标记的区别在于,它可能会更紧密地再现您解析的内容

<root><value></value><valueWithWhitespace>   </valueWithWhitespace></root>
var xml = XElement.Parse(
    "<root><value /><valueWithWhitespace>   </valueWithWhitespace></root>",
    LoadOptions.PreserveWhitespace
    );

var stringWriter = new StringWriter();
using (var xmlWriter = new CustomXmlTextWriter(stringWriter))
{
    xml.WriteTo(xmlWriter);
    xmlWriter.Flush();
    Console.WriteLine(stringWriter);
}
public class CustomXmlTextWriter : XmlTextWriter
{
    public CustomXmlTextWriter(TextWriter writer)
        : base(writer)
    {}

    public CustomXmlTextWriter(Stream stream, Encoding encoding)
        : base(stream, encoding)
    {}

    public CustomXmlTextWriter(string filename, Encoding encoding)
        : base(filename, encoding)
    {}

    public override void WriteEndElement()
    {
        this.WriteFullEndElement();
    } 
}
class CustomXmlTextWriter : XmlTextWriter {
    public CustomXmlTextWriter(MemoryStream stream) : base(stream, new UTF8Encoding(false)) { }

    public override void WriteEndElement() {
        base.WriteEndElement();
        base.Flush();
        var stream = (MemoryStream)BaseStream;
        var buffer = stream.GetBuffer();
        var pos = stream.Position;
        if (pos > 3 && buffer[pos - 1] == '>' && buffer[pos - 2] == '/' && buffer[pos - 3] == ' ') {
            stream.Seek(-3, SeekOrigin.Current);
            stream.WriteByte((byte)'/');
            stream.WriteByte((byte)'>');
        }
    }
}