1 #Region "Microsoft.VisualBasic::661e37630c61ceaf8afbf44ae58d82c9, Microsoft.VisualBasic.Core\Text\Xml\Linq\NodeIterator.vb"
2
3     ' Author:
4     
5     '       asuka (amethyst.asuka@gcmodeller.org)
6     '       xie (genetics@smrucc.org)
7     '       xieguigang (xie.guigang@live.com)
8     
9     ' Copyright (c) 2018 GPL3 Licensed
10     
11     
12     ' GNU GENERAL PUBLIC LICENSE (GPL3)
13     
14     
15     ' This program is free software: you can redistribute it and/or modify
16     ' it under the terms of the GNU General Public License as published by
17     ' the Free Software Foundation, either version 3 of the License, or
18     ' (at your option) any later version.
19     
20     ' This program is distributed in the hope that it will be useful,
21     ' but WITHOUT ANY WARRANTY; without even the implied warranty of
22     ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23     ' GNU General Public License for more details.
24     
25     ' You should have received a copy of the GNU General Public License
26     ' along with this program. If not, see <http://www.gnu.org/licenses/>.
27
28
29
30     ' /********************************************************************************/
31
32     ' Summaries:
33
34     '     Module NodeIterator
35     
36     '         FunctionGetArrayTemplate, IterateArrayNodes
37     
38     
39     ' /********************************************************************************/
40
41 #End Region
42
43 Imports System.Runtime.CompilerServices
44 Imports System.Xml
45 Imports Microsoft.VisualBasic.Language
46
47 Namespace Text.Xml.Linq
48
49     Public Module NodeIterator
50
51         Const ArrayOfTemplate$ = "<?xml version=""1.0"" encoding=""utf-16""?>
52 <ArrayOf{0} xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"">
53 %s
54 </ArrayOf{0}>"
55
56         ''' <summary>
57         ''' 可以将模板文本之中的``%s``替换为相应的Xml数组文本
58         ''' </summary>
59         ''' <typeparam name="T">
60         ''' 在.NET的XML序列化之中,数组元素的类型名称首字母会自动的被转换为大写形式
61         ''' </typeparam>
62         ''' <returns></returns>
63         <MethodImpl(MethodImplOptions.AggressiveInlining)>
64         Public Function GetArrayTemplate(Of T As Class)() As String
65             Return ArrayOfTemplate.Replace("{0}"GetType(T).GetNodeNameDefine.UpperCaseFirstChar)
66         End Function
67
68         ''' <summary>
69         ''' 使用<see cref="XmlDocument.Load"/>方法加载XML文档依旧是一次性的全部加载所有的文本到内存之中,第一次加载效率会比较低
70         ''' 则可以使用这个方法来加载非常大的XML文档
71         ''' </summary>
72         ''' <param name="path$"></param>
73         ''' <returns></returns>
74         <Extension> Public Iterator Function IterateArrayNodes(path$, tag$) As IEnumerable(Of String)
75             Dim buffer As New List(Of String)
76             Dim start$ = "<" & tag
77             Dim ends$ = $"</{tag}>"
78             Dim stack%
79             Dim tagOpen As Boolean = False
80             Dim lefts$
81             Dim i%
82
83             For Each line As String In path.IterateAllLines
84                 If tagOpen Then
85
86                     i = InStr(line, ends)
87
88                     If i > 0 Then
89                         ' 遇到了结束标签,则取出来
90                         If stack > 0 Then
91                             stack -= 1 ' 内部栈,还没有结束,则忽略当前的这个标签
92                         Else
93                             ' 这个是真正的结束标签
94                             lefts = Mid(line, i + ends.Length)
95                             buffer += ends
96                             tagOpen = False
97
98                             Yield buffer.JoinBy(vbLf)
99
100                             buffer *= 0
101                             buffer += lefts
102
103                             ' 这里要跳出来,否则后面buffer += line处任然会添加这个结束标签行的
104                             Continue For
105                         End If
106                     ElseIf InStr(line, start) > 0 Then
107                         stack += 1
108                     End If
109
110                     buffer += line
111                 Else
112                     ' 需要一直遍历到开始标签为止
113                     i = InStr(line, start)
114
115                     If i > 0 Then
116                         tagOpen = True
117                         buffer += Mid(line, i)
118                     End If
119                 End If
120             Next
121         End Function
122     End Module
123 End Namespace