【问题标题】:XMLWriterTraceListener produces wall-of-text instead of formatted XMLXMLWriterTraceListener 生成文本墙而不是格式化的 XML
【发布时间】:2014-03-20 18:54:19
【问题描述】:

我有一个 XMLWriterTraceListener 对象像这样添加到我的跟踪侦听器中,

System.Diagnostics.XmlWriterTraceListener xmlTrace = new 
    System.Diagnostics.XmlWriterTraceListener("Trace.xml");
xmlTrace.IndentLevel = 1;
xmlTrace.IndentSize = 4;

System.Diagnostics.Trace.Listeners.Add(xmlTrace);

并且它成功地接收到来自 Trace.WriteLine()、Trace.TraceInformation() 等的消息。唯一的问题是它正在写入的 Trace.xml 文件不可读,因为它不包含换行符或缩进。我是否遗漏了一个中间步骤(XMLStreamWriter?)来美化输出?

当前输出为:

<E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent"><System xmlns="http://schemas.microsoft.com/2004/06/windows/eventlog/system"><EventID>0</EventID><Type>3</Type><SubType Name="Information">0</SubType><Level>8</Level><TimeCreated SystemTime="2014-03-20T18:05:43.2778822Z" /><Source Name="Program.vshost.exe" /><Correlation ActivityID="{00000000-0000-0000-0000-000000000000}" /><Execution ProcessName="Program.vshost" ProcessID="6840" ThreadID="9" /><Channel/><Computer>ODYSSEY</Computer></System><ApplicationData>Startup!</ApplicationData></E2ETraceEvent>

但我想阅读:

<E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent">
    <System xmlns="http://schemas.microsoft.com/2004/06/windows/eventlog/system">
        <EventID>0</EventID>
        <Type>3</Type>
        <SubType Name="Information">0</SubType>
        <Level>8</Level>
        <TimeCreated SystemTime="2014-03-20T18:05:43.2778822Z" />
        <Source Name="Program.vshost.exe" />
        <Correlation ActivityID="{00000000-0000-0000-0000-000000000000}" />
        <Execution ProcessName="Program.vshost" ProcessID="6840" ThreadID="9" />
        <Channel/>
        <Computer>ODYSSEY</Computer>
    </System>
    <ApplicationData>Startup!</ApplicationData>
</E2ETraceEvent>

【问题讨论】:

    标签: c# xml logging tracelistener


    【解决方案1】:

    看起来没有任何方法可以做到这一点,甚至没有反射: http://dotnetinside.com/en/framework/v4.0.30319/System/XmlWriterTraceListener

    如果您可以在单声道版本中获得 xml 编写器设置,您也许可以: http://dotnetinside.com/en/framework/Mono+Framework/System/XmlWriterTraceListener

    您可以使用服务跟踪查看器打开 XML 跟踪: http://msdn.microsoft.com/en-us/library/ms732023%28v=vs.110%29.aspx

    否则,复制并粘贴到您喜欢的 IDE 或 XML 编辑器。

    【讨论】:

    • 感谢,但我将推迟接受作为答案,因为我对 XmlWriterTraceListener 对象的 IndentSize 和 IndentLevel 属性的存在完全感到困惑。
    • 它们是基类属性(TextWriterListener 具有这些属性并在 WriteLine 上使用它们)。从类派生的类可以覆盖方法(XmlWriterTraceListener 可以)并且它可以忽略对 TextWriterTraceListener 很重要的事情(XmlWRiterTraceListener 确实会忽略这些值)。 Systems.Diagnostic 不是最好的 API,它在 .NET 1.0 中是一成不变的,并且有很多缺陷(比如提供派生类不使用或不关心的属性的基类)
    • 这可以通过反射来控制,不理想,但可行。我个人反编译 BCL 实现,然后根据自己的喜好自定义它们。我喜欢 .NET 的跟踪工具,但我希望 BCL 侦听器实现更健壮/可配置。
    【解决方案2】:

    有点晚了,但是如果您想在代码中执行此操作,下面的链接很好地展示了我们如何读取 XML。您可以读取子树,然后可能反序列化为一个类。然后使用适当的设置将其序列化回 XML。

    我还从 E2ETraceEvent Xml 节点创建了 C# 类,以便我反序列化 Xml 片段。

    http://haishibai.blogspot.in/2009/04/monitoring-and-reading-svclog-file.html

    示例代码:

    using (var fileStream = new FileStream(logFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
    using (XmlReader reader = new XmlTextReader(fileStream, XmlNodeType.Element, null))
    {
        while (reader.Read())
        {
            if (reader.Name == "E2ETraceEvent" && reader.NodeType == XmlNodeType.Element)
            {
                using (XmlReader subReader = reader.ReadSubtree())
                {
                    while (subReader.Read())
                    {
                        var elementString = subReader.ReadOuterXml();
                        if (!string.IsNullOrWhiteSpace(elementString))
                        {
                            using (var xStream = this.GenerateStreamFromString(elementString))
                            {
                                XElement traceElement = XElement.Load(xStream);
                                var serializer = new XmlSerializer(typeof(E2ETraceEvent));
                                var traceObject = (E2ETraceEvent)serializer.Deserialize(traceElement.CreateReader());
    
                                var formattedXml = this.SerializeToXmlString<E2ETraceEvent>(traceObject); 
                            }
                        }
                    }
                }
            }
        }
    }
    ====================================
    
    private Stream GenerateStreamFromString(string s)
    {
        var stream = new MemoryStream();
        var writer = new StreamWriter(stream);
        writer.Write(s);
        writer.Flush();
        stream.Position = 0;
        return stream;
    }
    =====================================
    
    private string SerializeToXmlString<T>(T objectToSerialize)
    {
        XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
        var settings = new XmlWriterSettings
        {
            Indent = true,
            OmitXmlDeclaration = true
        };
        var xml = string.Empty;
    
        using (var sw = new StringWriter())
        {
            using (XmlWriter writer = XmlWriter.Create(sw, settings))
            {
                xmlSerializer.Serialize(writer, objectToSerialize);
                xml = sw.ToString();
            }
        }
    
        return xml;
    }
    ======================================
    

    希望这会有所帮助!

    【讨论】:

      【解决方案3】:

      您可以使用服务跟踪查看器工具 (SvcTraceViewer.exe) 来读取 System.Diagnostics.XmlWriterTraceListener 的输出。

      https://docs.microsoft.com/en-us/dotnet/framework/wcf/service-trace-viewer-tool-svctraceviewer-exe

      它应该是 Windows SDK 的一部分 (https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk)

      并且可以在 Microsoft SDKs 目录下的某处找到。例如:

      C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools\SvcTraceViewer.exe
      

      【讨论】:

        猜你喜欢
        • 2012-02-15
        • 2016-03-05
        • 2013-06-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-08-20
        • 1970-01-01
        相关资源
        最近更新 更多