You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何自定义XmlWriter的序列化输出以移除空元素末尾的空格?

如何自定义XmlWriter的序列化输出以移除空元素末尾的空格?

碰到这种内部类没法直接继承修改的情况确实头疼,不过有两个实用的办法能解决空元素末尾带空格的问题,给你详细说说:

方法一:直接处理生成后的字符串

因为你是用StringBuilder来存储XML输出的,这种方法最简单粗暴——等XmlWriter写完所有内容后,直接对生成的字符串做替换,把所有的 />替换成/>就行:

// 在XmlWriter完成写入操作后执行
string finalXml = sbXmlDoc.ToString().Replace(" />", "/>");

这种方案适合场景简单的情况,一般XML里不会出现文本节点包含 />的情况,所以不用担心误替换的问题。

方法二:包装XmlWriter自定义空元素输出

如果不想做字符串替换,也可以写一个自定义的XmlWriter包装类,把所有操作转发给原有的XmlWriter,只重写WriteEndElement方法来控制空元素的输出格式:

首先定义这个包装类:

public class CustomXmlWriter : XmlWriter
{
    private readonly XmlWriter _innerWriter;
    private bool _isEmptyElement;

    public CustomXmlWriter(XmlWriter innerWriter)
    {
        _innerWriter = innerWriter;
    }

    public override void WriteStartElement(string prefix, string localName, string ns)
    {
        // 标记当前元素初始状态为“空元素”
        _isEmptyElement = true;
        _innerWriter.WriteStartElement(prefix, localName, ns);
    }

    // 只要元素内写入了内容,就标记为非空元素
    public override void WriteString(string text)
    {
        _isEmptyElement = false;
        _innerWriter.WriteString(text);
    }

    public override void WriteEndElement()
    {
        if (_isEmptyElement)
        {
            // 空元素直接输出不带空格的闭合标签
            _innerWriter.WriteRaw("/>");
            _isEmptyElement = false;
        }
        else
        {
            // 非空元素按正常逻辑处理
            _innerWriter.WriteEndElement();
        }
    }

    // 以下是必须重写的XmlWriter抽象方法,全部转发给内部的XmlWriter即可
    public override void Flush() => _innerWriter.Flush();
    public override string LookupPrefix(string ns) => _innerWriter.LookupPrefix(ns);
    public override void WriteBase64(byte[] buffer, int index, int count) => _innerWriter.WriteBase64(buffer, index, count);
    public override void WriteCData(string text) => _innerWriter.WriteCData(text);
    public override void WriteCharEntity(char ch) => _innerWriter.WriteCharEntity(ch);
    public override void WriteChars(char[] buffer, int index, int count) => _innerWriter.WriteChars(buffer, index, count);
    public override void WriteComment(string text) => _innerWriter.WriteComment(text);
    public override void WriteDocType(string name, string pubid, string sysid, string subset) => _innerWriter.WriteDocType(name, pubid, sysid, subset);
    public override void WriteEndDocument() => _innerWriter.WriteEndDocument();
    public override void WriteEntityRef(string name) => _innerWriter.WriteEntityRef(name);
    public override void WriteFullEndElement() => _innerWriter.WriteFullEndElement();
    public override void WriteProcessingInstruction(string name, string text) => _innerWriter.WriteProcessingInstruction(name, text);
    public override void WriteRaw(string data) => _innerWriter.WriteRaw(data);
    public override void WriteRaw(char[] buffer, int index, int count) => _innerWriter.WriteRaw(buffer, index, count);
    public override void WriteStartAttribute(string prefix, string localName, string ns) => _innerWriter.WriteStartAttribute(prefix, localName, ns);
    public override void WriteStartDocument(bool standalone) => _innerWriter.WriteStartDocument(standalone);
    public override void WriteStartDocument() => _innerWriter.WriteStartDocument();
    public override void WriteSurrogateCharEntity(char lowChar, char highChar) => _innerWriter.WriteSurrogateCharEntity(lowChar, highChar);
    public override void WriteWhitespace(string ws) => _innerWriter.WriteWhitespace(ws);
    public override XmlWriterSettings Settings => _innerWriter.Settings;
    public override WriteState WriteState => _innerWriter.WriteState;
    public override XmlSpace XmlSpace => _innerWriter.XmlSpace;
}

然后使用的时候,把原本创建的XmlWriter包装起来就行:

XmlWriter innerWriter = XmlWriter.Create(sbXmlDoc, new XmlWriterSettings {
    Indent = true,
    IndentChars = "  ",
    OmitXmlDeclaration = true
});

using (var customWriter = new CustomXmlWriter(innerWriter))
{
    // 这里用customWriter来完成你的XML写入操作
    // 示例:
    // customWriter.WriteStartElement("root");
    // customWriter.WriteStartElement("emptyElement");
    // customWriter.WriteEndElement();
    // customWriter.WriteEndElement();
}

这种方法更灵活,也避免了字符串替换的潜在风险,适合复杂的XML生成场景。

另外提一句:虽然XmlTextWriter现在不推荐使用,但如果你的场景特别简单,也可以试试它——它默认输出的空元素就是不带空格的/>,不过还是更推荐上面两种符合官方XmlWriter.Create规范的方案。

备注:内容来源于stack exchange,提问作者Jez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 09:14:32