创建没有 xmlns 名称空间声明的 XML 片段

Create XML fragment without xmlns namespace declaration

我正在尝试通过代码创建以下 XML:

<log4j:event logger="MyTools" level="WARN" timestamp="763">
  <log4j:message>This is a log message.</log4j:message>
</log4j:event>

但是我没能去掉添加的xmlns:log4j="http://my-project.org/log4j/"。目前我正在测试以下代码(参见 HERE):

XNamespace ns = "http://my-project.org/log4j/";
var root = new XElement("root", new XAttribute(XNamespace.Xmlns + "log4j", ns));
var eventElement = new XElement(ns + "event");
root.Add(eventElement);
    
eventElement.SetAttributeValue("logger", "MyTools");
eventElement.SetAttributeValue("level", "WARN");
eventElement.SetAttributeValue("timestamp", DateTime.Now.Millisecond);
    
eventElement.SetElementValue(ns + "message", "This is a log message.");

当我将 eventElement 转换为字符串时,我将命名空间添加到 log4j:event 节点,当转换 root 时,它仅添加到根元素(因为它应该是 IMO对于有效的 XML),但是 如何在没有名称空间声明的情况下仅获取事件节点作为仅 XML fragment/node? 我也尝试过使用 XmlWriter 但结果相同。
我也对其他方法持开放态度。

目前我使用 String.Replace(" xmlns:log4j=\"" + ns + "\"", string.Empty) 来摆脱它,但这相当慢(使完整方法慢 ~50%)并且因为这可能发生在高频率(=logger)我想尽快完成。
我需要它而不声明名称空间的原因是一些日志侦听器不喜欢名称空间并且如果它存在就会崩溃(日志通过 UDP 发送到日志侦听器)。

我想要改进的是以下 NLog 渲染器:
https://github.com/NLog/NLog/blob/master/src/NLog/LayoutRenderers/Log4JXmlEventLayoutRenderer.cs
除了缓慢的 Replace(参见 Ln 300)之外,我还替换了调用站点 / UserStackFrame 以使用 [CallerMemberName] 参数以及由我自己的日志包装器实现的参数。我可以将日志生成从测试系统上的 >100ms/1k 日志加速到 ~35ms/1k,只要将命名空间保留在那里(对于有效的 XML 来说应该如此),但正如已经说过的一些日志监听器(即哨兵)在那里时崩溃...

您显示的代码段在 XML 世界中格式正确,没有名称空间,如果您确实需要使用 .NET 创建这样的代码段,那么遗留 XmlTextWriter 允许如下:

        using (StringWriter sw = new StringWriter())
        {

            using (XmlTextWriter xtw = new XmlTextWriter(sw))
            {
                xtw.Namespaces = false;
                xtw.Formatting = Formatting.Indented;
                xtw.WriteStartElement("log4j:event");
                xtw.WriteAttributeString("logger", "MyTools");
                xtw.WriteAttributeString("level", "WARN");
                xtw.WriteAttributeString("timestamp", "763");
                xtw.WriteElementString("log4j:message", "This is a log message.");
                xtw.WriteEndElement();
            }
            string result = sw.ToString();
            Console.WriteLine(result);
        }

结果:

<log4j:event logger="MyTools" level="WARN" timestamp="763">
  <log4j:message>This is a log message.</log4j:message>
</log4j:event>

但是请注意,现在大多数 XML 解析器和 API 都期望名称空间格式正确 XML(只有当冒号之前的前缀绑定到名称空间时才允许使用带冒号的名称) 因此无法使用 LINQ to XML 处理创建的代码段,或者使用 XmlReader.Create.

创建的默认 XmlReader