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 Title attribute of a TocEntry
- Sort a TOC with a multi-level hierarchy in ascending order by the Title attribute of a TocEntry and respect the level structure
The UI is left to you.
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.
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’ll post a full sample project in a later post.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
Imports System.Xml Public Class Form1 Private NewToc As XDocument Private Sub ButtonOpen_Click(sender As System.Object, e As System.EventArgs) Handles ButtonOpen.Click OpenFileDialogToc.ShowDialog() End Sub Private Sub ButtonSave_Click(sender As System.Object, e As System.EventArgs) Handles ButtonSave.Click If String.IsNullOrWhiteSpace(OpenFileDialogToc.FileName) Or Not My.Computer.FileSystem.FileExists(OpenFileDialogToc.FileName) Then MsgBox("A file has not been selected.") Else SaveFileDialogToc.ShowDialog() End If End Sub Private Sub OpenFileDialogToc_FileOk(sender As System.Object, e As System.ComponentModel.CancelEventArgs) Handles OpenFileDialogToc.FileOk Dim Toc As XmlDocument = New XmlDocument() Toc.Load(OpenFileDialogToc.FileName) RefreshTree(Toc) NewToc = XDocument.Load(OpenFileDialogToc.FileName) End Sub Private Sub RefreshTree(ByVal Toc As XmlDocument) TreeViewToc.Nodes.Clear() TreeViewToc.Nodes.Add(New TreeNode()) Dim TocNode As TreeNode = New TreeNode() TocNode = TreeViewToc.Nodes(0) AddNodeToDisplay(Toc.DocumentElement, TocNode) TreeViewToc.ExpandAll() End Sub Private Sub AddNodeToDisplay(ByVal InTocFileNode As XmlNode, ByVal InTocTreeNode As TreeNode) Dim TocFileNode As XmlNode Dim TocTreeNode As TreeNode Dim TocFileNodeList As XmlNodeList If InTocFileNode.HasChildNodes Then TocFileNodeList = InTocFileNode.ChildNodes For i As Integer = 0 To TocFileNodeList.Count - 1 Step 1 TocFileNode = InTocFileNode.ChildNodes(i) InTocTreeNode.Nodes.Add(New TreeNode(TocFileNode.Attributes("Title").Value)) TocTreeNode = InTocTreeNode.Nodes(i) AddNodeToDisplay(TocFileNode, TocTreeNode) Next Else InTocTreeNode.Text = InTocFileNode.Attributes("Title").Value End If End Sub Private Sub Flatten(ByVal Toc As String) If String.IsNullOrWhiteSpace(OpenFileDialogToc.FileName) Or Not My.Computer.FileSystem.FileExists(OpenFileDialogToc.FileName) Then MsgBox("A file has not been selected.") Else Dim TocXml As XDocument = XDocument.Load(Toc) Dim FlatToc As XDocument = _ <?xml version="1.0" encoding="utf-8"?> <CatapultToc Version="1"> </CatapultToc> For Each element In TocXml.Root.Descendants Dim element2 As XElement = _ <TocEntry></TocEntry> For Each attr In element.Attributes element2.SetAttributeValue(attr.Name, attr.Value) Next FlatToc.Root.Add(element2) Next NewToc = FlatToc LabelChangeApplied.Text = "Flattened" Dim xd As New XmlDocument Dim xr = FlatToc.CreateReader() xd.Load(xr) RefreshTree(xd) End If End Sub Private Sub SortTopNodes(ByVal Toc As String) If String.IsNullOrWhiteSpace(OpenFileDialogToc.FileName) Or Not My.Computer.FileSystem.FileExists(OpenFileDialogToc.FileName) Then MsgBox("A file has not been selected.") Else Dim TocXml As XDocument = XDocument.Load(Toc) Dim SortedToc As XDocument = _ <?xml version="1.0" encoding="utf-8"?> <CatapultToc Version="1"> </CatapultToc> Dim ChildrenOfCatapultToc = From xElement In TocXml.Root.Elements _ Order By CStr(xElement.Attribute("Title")) Ascending _ Select xElement SortedToc.Root.Add(ChildrenOfCatapultToc) NewToc = SortedToc LabelChangeApplied.Text = "Top nodes sorted" Dim xd As New XmlDocument Dim xr = SortedToc.CreateReader() xd.Load(xr) RefreshTree(xd) End If End Sub Private Sub SortInnerNodes(ByVal Toc As String) If String.IsNullOrWhiteSpace(OpenFileDialogToc.FileName) Or Not My.Computer.FileSystem.FileExists(OpenFileDialogToc.FileName) Then MsgBox("A file has not been selected.") Else Dim TocXml As XDocument = XDocument.Load(Toc) Dim SortedToc As XDocument = _ <?xml version="1.0" encoding="utf-8"?> <CatapultToc Version="1"> </CatapultToc> SortTocEntry(TocXml.Root) SortedToc.Root.ReplaceWith(TocXml.Root) NewToc = SortedToc LabelChangeApplied.Text = "All nodes sorted" Dim xd As New XmlDocument Dim xr = SortedToc.CreateReader() xd.Load(xr) RefreshTree(xd) End If End Sub Private Sub SortTocEntry(ByVal tocEntry As XElement) If tocEntry.HasElements Then For Each entry In tocEntry.Elements SortTocEntry(entry) Next tocEntry.ReplaceNodes(From xElement In tocEntry.Elements _ Order By CStr(xElement.Attribute("Title")) Ascending _ Select xElement) End If End Sub Private Sub ButtonFlatten_Click(sender As System.Object, e As System.EventArgs) Handles ButtonFlatten.Click Flatten(OpenFileDialogToc.FileName) End Sub Private Sub SaveFileDialogToc_FileOk(sender As System.Object, e As System.ComponentModel.CancelEventArgs) Handles SaveFileDialogToc.FileOk NewToc.Save(SaveFileDialogToc.FileName) End Sub Private Sub ButtonSortTopNodes_Click(sender As System.Object, e As System.EventArgs) Handles ButtonSortTopNodes.Click SortTopNodes(OpenFileDialogToc.FileName) End Sub Private Sub ButtonSortInnerNodes_Click(sender As System.Object, e As System.EventArgs) Handles ButtonSortInnerNodes.Click SortInnerNodes(OpenFileDialogToc.FileName) End Sub End Class |