{"id":284,"date":"2012-11-27T02:14:08","date_gmt":"2012-11-27T02:14:08","guid":{"rendered":"http:\/\/tregner.com\/flare-blog\/?p=284"},"modified":"2012-12-08T03:12:25","modified_gmt":"2012-12-08T03:12:25","slug":"sorting-tocs-in-a-project","status":"publish","type":"post","link":"https:\/\/tregner.com\/flare-blog\/sorting-tocs-in-a-project\/","title":{"rendered":"Sorting TOCs in a Project"},"content":{"rendered":"<p>TOC sorting is probably only useful for reference documentation. But please post comments with any use-cases for TOC sorting you can think of. My desire to sort a TOC is threefold. I want to be able to:<\/p>\n<ul>\n<li>Flatten a TOC with levels down to one level<\/li>\n<li>Sort a flattened TOC in ascending order by the Title attribute of a TocEntry<\/li>\n<li>Sort a TOC with a multi-level hierarchy in ascending order by the Title attribute of a TocEntry and respect the level structure<\/li>\n<\/ul>\n<p>The UI is left to you.<\/p>\n<p>Create a Visual Basic Windows Forms project and build a form with items which correspond to the procedures in the sample. An open file dialog is necessary to select the TOC. With the dialogs, limit the file type to *.fltoc. The TOC structure is rendered in a tree view. I placed it prominently in the center of the form. I used buttons for the options. But radio buttons would make more sense.<\/p>\n<p>A preview of the options display in the tree view when a button is clicked. But nothing is saved until the save dialog is shown. You can use that to overwrite or to create a new TOC. If I see any use-cases, I&#8217;ll post a full sample project in a later post.<\/p>\n<pre>Imports System.Xml\r\n\r\nPublic Class Form1\r\n\r\n    Private NewToc As XDocument\r\n\r\n    Private Sub ButtonOpen_Click(sender As System.Object, e As System.EventArgs) Handles ButtonOpen.Click\r\n        OpenFileDialogToc.ShowDialog()\r\n    End Sub\r\n\r\n    Private Sub ButtonSave_Click(sender As System.Object, e As System.EventArgs) Handles ButtonSave.Click\r\n        If String.IsNullOrWhiteSpace(OpenFileDialogToc.FileName) Or Not My.Computer.FileSystem.FileExists(OpenFileDialogToc.FileName) Then\r\n            MsgBox(\"A file has not been selected.\")\r\n        Else\r\n            SaveFileDialogToc.ShowDialog()\r\n        End If\r\n    End Sub\r\n\r\n    Private Sub OpenFileDialogToc_FileOk(sender As System.Object, e As System.ComponentModel.CancelEventArgs) Handles OpenFileDialogToc.FileOk\r\n        Dim Toc As XmlDocument = New XmlDocument()\r\n        Toc.Load(OpenFileDialogToc.FileName)\r\n        RefreshTree(Toc)\r\n\r\n        NewToc = XDocument.Load(OpenFileDialogToc.FileName)\r\n    End Sub\r\n\r\n    Private Sub RefreshTree(ByVal Toc As XmlDocument)\r\n        TreeViewToc.Nodes.Clear()\r\n        TreeViewToc.Nodes.Add(New TreeNode())\r\n        Dim TocNode As TreeNode = New TreeNode()\r\n        TocNode = TreeViewToc.Nodes(0)\r\n        AddNodeToDisplay(Toc.DocumentElement, TocNode)\r\n        TreeViewToc.ExpandAll()\r\n    End Sub\r\n\r\n    Private Sub AddNodeToDisplay(ByVal InTocFileNode As XmlNode, ByVal InTocTreeNode As TreeNode)\r\n        Dim TocFileNode As XmlNode\r\n        Dim TocTreeNode As TreeNode\r\n        Dim TocFileNodeList As XmlNodeList\r\n\r\n        If InTocFileNode.HasChildNodes Then\r\n            TocFileNodeList = InTocFileNode.ChildNodes\r\n            For i As Integer = 0 To TocFileNodeList.Count - 1 Step 1\r\n                TocFileNode = InTocFileNode.ChildNodes(i)\r\n                InTocTreeNode.Nodes.Add(New TreeNode(TocFileNode.Attributes(\"Title\").Value))\r\n                TocTreeNode = InTocTreeNode.Nodes(i)\r\n                AddNodeToDisplay(TocFileNode, TocTreeNode)\r\n            Next\r\n        Else\r\n            InTocTreeNode.Text = InTocFileNode.Attributes(\"Title\").Value\r\n        End If\r\n    End Sub\r\n\r\n    Private Sub Flatten(ByVal Toc As String)\r\n        If String.IsNullOrWhiteSpace(OpenFileDialogToc.FileName) Or Not My.Computer.FileSystem.FileExists(OpenFileDialogToc.FileName) Then\r\n            MsgBox(\"A file has not been selected.\")\r\n        Else\r\n            Dim TocXml As XDocument = XDocument.Load(Toc)\r\n            Dim FlatToc As XDocument = _\r\n                &lt;?xml version=\"1.0\" encoding=\"utf-8\"?&gt;\r\n                &lt;CatapultToc\r\n                    Version=\"1\"&gt;\r\n                &lt;\/CatapultToc&gt;\r\n\r\n            For Each element In TocXml.Root.Descendants\r\n                Dim element2 As XElement = _\r\n                    &lt;TocEntry&gt;&lt;\/TocEntry&gt;\r\n                For Each attr In element.Attributes\r\n                    element2.SetAttributeValue(attr.Name, attr.Value)\r\n                Next\r\n                FlatToc.Root.Add(element2)\r\n            Next\r\n\r\n            NewToc = FlatToc\r\n            LabelChangeApplied.Text = \"Flattened\"\r\n\r\n            Dim xd As New XmlDocument\r\n            Dim xr = FlatToc.CreateReader()\r\n            xd.Load(xr)\r\n            RefreshTree(xd)\r\n        End If\r\n    End Sub\r\n\r\n    Private Sub SortTopNodes(ByVal Toc As String)\r\n        If String.IsNullOrWhiteSpace(OpenFileDialogToc.FileName) Or Not My.Computer.FileSystem.FileExists(OpenFileDialogToc.FileName) Then\r\n            MsgBox(\"A file has not been selected.\")\r\n        Else\r\n            Dim TocXml As XDocument = XDocument.Load(Toc)\r\n            Dim SortedToc As XDocument = _\r\n                &lt;?xml version=\"1.0\" encoding=\"utf-8\"?&gt;\r\n                &lt;CatapultToc\r\n                    Version=\"1\"&gt;\r\n                &lt;\/CatapultToc&gt;\r\n\r\n            Dim ChildrenOfCatapultToc = From xElement In TocXml.Root.Elements _\r\n                                    Order By CStr(xElement.Attribute(\"Title\")) Ascending _\r\n                                    Select xElement\r\n\r\n            SortedToc.Root.Add(ChildrenOfCatapultToc)\r\n\r\n            NewToc = SortedToc\r\n            LabelChangeApplied.Text = \"Top nodes sorted\"\r\n\r\n            Dim xd As New XmlDocument\r\n            Dim xr = SortedToc.CreateReader()\r\n            xd.Load(xr)\r\n            RefreshTree(xd)\r\n        End If\r\n    End Sub\r\n    Private Sub SortInnerNodes(ByVal Toc As String)\r\n\r\n        If String.IsNullOrWhiteSpace(OpenFileDialogToc.FileName) Or Not My.Computer.FileSystem.FileExists(OpenFileDialogToc.FileName) Then\r\n            MsgBox(\"A file has not been selected.\")\r\n        Else\r\n            Dim TocXml As XDocument = XDocument.Load(Toc)\r\n            Dim SortedToc As XDocument = _\r\n                &lt;?xml version=\"1.0\" encoding=\"utf-8\"?&gt;\r\n                &lt;CatapultToc\r\n                    Version=\"1\"&gt;\r\n                &lt;\/CatapultToc&gt;\r\n\r\n            SortTocEntry(TocXml.Root)\r\n\r\n            SortedToc.Root.ReplaceWith(TocXml.Root)\r\n\r\n            NewToc = SortedToc\r\n            LabelChangeApplied.Text = \"All nodes sorted\"\r\n\r\n            Dim xd As New XmlDocument\r\n            Dim xr = SortedToc.CreateReader()\r\n            xd.Load(xr)\r\n            RefreshTree(xd)\r\n        End If\r\n    End Sub\r\n\r\n    Private Sub SortTocEntry(ByVal tocEntry As XElement)\r\n        If tocEntry.HasElements Then\r\n            For Each entry In tocEntry.Elements\r\n                SortTocEntry(entry)\r\n            Next\r\n            tocEntry.ReplaceNodes(From xElement In tocEntry.Elements _\r\n                                Order By CStr(xElement.Attribute(\"Title\")) Ascending _\r\n                                Select xElement)\r\n        End If\r\n    End Sub\r\n\r\n    Private Sub ButtonFlatten_Click(sender As System.Object, e As System.EventArgs) Handles ButtonFlatten.Click\r\n        Flatten(OpenFileDialogToc.FileName)\r\n    End Sub\r\n\r\n    Private Sub SaveFileDialogToc_FileOk(sender As System.Object, e As System.ComponentModel.CancelEventArgs) Handles SaveFileDialogToc.FileOk\r\n        NewToc.Save(SaveFileDialogToc.FileName)\r\n    End Sub\r\n\r\n    Private Sub ButtonSortTopNodes_Click(sender As System.Object, e As System.EventArgs) Handles ButtonSortTopNodes.Click\r\n        SortTopNodes(OpenFileDialogToc.FileName)\r\n    End Sub\r\n\r\n    Private Sub ButtonSortInnerNodes_Click(sender As System.Object, e As System.EventArgs) Handles ButtonSortInnerNodes.Click\r\n        SortInnerNodes(OpenFileDialogToc.FileName)\r\n    End Sub\r\n\r\nEnd Class\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>TOC sorting is probably only useful for reference documentation. But please post comments with any use-cases for TOC sorting you can think of. My desire to sort a TOC is threefold. I want to be able to: Flatten a TOC with levels down to one level Sort a flattened TOC in ascending order by the&hellip; <a class=\"more-link\" href=\"https:\/\/tregner.com\/flare-blog\/sorting-tocs-in-a-project\/\">Continue reading <span class=\"screen-reader-text\">Sorting TOCs in a Project<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[4],"tags":[5,47,15,48],"_links":{"self":[{"href":"https:\/\/tregner.com\/flare-blog\/wp-json\/wp\/v2\/posts\/284"}],"collection":[{"href":"https:\/\/tregner.com\/flare-blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tregner.com\/flare-blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tregner.com\/flare-blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tregner.com\/flare-blog\/wp-json\/wp\/v2\/comments?post=284"}],"version-history":[{"count":18,"href":"https:\/\/tregner.com\/flare-blog\/wp-json\/wp\/v2\/posts\/284\/revisions"}],"predecessor-version":[{"id":302,"href":"https:\/\/tregner.com\/flare-blog\/wp-json\/wp\/v2\/posts\/284\/revisions\/302"}],"wp:attachment":[{"href":"https:\/\/tregner.com\/flare-blog\/wp-json\/wp\/v2\/media?parent=284"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tregner.com\/flare-blog\/wp-json\/wp\/v2\/categories?post=284"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tregner.com\/flare-blog\/wp-json\/wp\/v2\/tags?post=284"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}