1

I'm trying to use System.Xml.Linq to implement some logging for a small hobby application. I have a few strings that I would like to display in multi-line indented format for clarity, but I cannot get any xml viewer to recognize newline characters. I've found several related posts (a) (b) (c) (d) (e) but the method described doesn't seem to work. My logging code looks as follows:

public static void InitializeNewReport(NPCInfo npcInfo)
    {
        if (Logger.Instance.LogCurrentNPC)
        {
            npcInfo.Report = new XElement("Report");
            npcInfo.CurrentElement = npcInfo.Report;
            npcInfo.ReportElementHierarchy = new Dictionary<XElement, XElement>();
         
            LogReport("Patching NPC " + npcInfo.LogReportingString, false, npcInfo);
            Logger.Instance.CurrentNPC = npcInfo;
        }
    }

    public static void OpenReportSubsection(string header, NPCInfo npcInfo)
    {
        if (Logger.Instance.LogCurrentNPC)
        {
            var newElement = new XElement(header);
            npcInfo.ReportElementHierarchy.Add(newElement, npcInfo.CurrentElement);
            npcInfo.CurrentElement.Add(newElement);
            npcInfo.CurrentElement = newElement;
        }
    }

    public static void LogReport(string message, bool triggerSave, NPCInfo npcInfo) // detailed operation log; not reflected on screen
    {
        if (Logger.Instance.LogCurrentNPC)
        {
            AddStringToReport(npcInfo.CurrentElement, message);

            if (triggerSave)
            {
                Logger.Instance.SaveCurrentNPCLog = true;
            }
        }
    }

    private static void AddStringToReport(XElement element, string value)
    {
        var split = value.Trim().Split(Environment.NewLine);
        foreach (var item in split)
        {
            element.Add(item);
            element.Add(Environment.NewLine);
        }
    }

    public static void CloseReportSubsection(NPCInfo npcInfo)
    {
        if (Logger.Instance.LogCurrentNPC)
        {
            npcInfo.CurrentElement = npcInfo.ReportElementHierarchy[npcInfo.CurrentElement];
        }
    }

    public static void SaveReport(NPCInfo npcInfo)
    {
        if (Logger.Instance.LogCurrentNPC)
        {
            if (Logger.Instance.SaveCurrentNPCLog)
            {
                string outputFile = System.IO.Path.Combine(PatcherSettings.Paths.LogFolderPath, Logger.Instance.PatcherExecutionStart.ToString("yyyy-MM-dd-HH-mm", System.Globalization.CultureInfo.InvariantCulture), Logger.Instance.CurrentNPC.LogReportingString + ".xml");

                XDocument output = new XDocument();
                output.Add(npcInfo.Report);

                var file = new System.IO.FileInfo(outputFile);
                file.Directory.Create(); // If the directory already exists, this method does nothing.
                output.Save(outputFile);
            }

            Logger.Instance.LogCurrentNPC = false;
            Logger.Instance.SaveCurrentNPCLog = false;
        }
    }

When viewed in a browser (Firefox), the resulting log does not preserve the newlines. When viewed in Notepad++, the log does preserve the newlines but doesn't preserve the collapsible sections because it places the section tags adjacent to each other. I can manually add a line break between the sections to make NP++ recognize them as collapsible but that's not a scalable solution. I've also tried replacing

foreach (var item in split)
        {
            element.Add(item);
            element.Add(Environment.NewLine);
        }

with

foreach (var item in split)
        {
            element.Add(item);
            element.Add("&#10;&#13;");
        }

as suggested in the linked posts but this just gets incorporated as a literal in the output xml. Indeed, when I try to use an online xml viewer, none of the methods in the linked posts seem to work with a small demo input.

Based on the referenced posts it seems like what I want should be possible, but I'm at a loss as to how to implement it. Could someone please suggest a solution?

A Piranha
  • 35
  • 4
  • Although said you cite [(a), a canonical answer regarding line breaks in XML files](https://stackoverflow.com/q/35504890/290085), the rest of your question proceeds as if you did not understand its key point that how line breaks are rendered is *application-specific*. There is no universal solution because the XML standard doesn't demand that applications render line breaks in XML files in any particular manner. – kjhughes Jan 06 '22 at 00:44
  • Add differing OS conventions to differing application semantics and you can hopefully see why you shouldn't be expecting rendering/viewing consistency at this level. HTML uses `
    ` for line breaks to conquer these challenges, for example.
    – kjhughes Jan 06 '22 at 00:57

0 Answers0