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

时间:2016-08-22 09:30:20

标签: c# xml linq-to-xml xelement xmlwriter

我正在尝试通过代码创建以下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片段/节点而没有名称空间声明? 我也尝试过使用XmlWriter但结果相同。
我也对其他方式持开放态度。

目前我使用String.Replace(" xmlns:log4j=\"" + ns + "\"", string.Empty)摆脱它,但这相当慢(使整个方法慢50%)并且因为这可能发生在高频率(=记录器)我想使它尽可能快。
我需要它而没有名称空间声明的原因是某些日志监听器不喜欢命名空间并且如果它存在则崩溃(日志通过UDP发送给日志监听器)。

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

1 个答案:

答案 0 :(得分:1)

您所展示的代码段在没有名称空间的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。