2013-03-17 111 views
1

我将通过示例代码解释我的情况。我的功能GetDox看起来很接近,但它仍然不完整。这是一个测试代码。使用RegExp选择范围

'test begin... 
'<dox> 
' <member type="Public Sub" name="Increment" return="void"> 
' <param type="Integer" name="nBase" out="true" /> 
' <param type="Integer" name="nStep" out="false" /> 
' <purpose> 
'  purpose here... 
' </purpose> 
' </member> 
' <member ... /> 
'</dox> 
'other comments here... 
Public Sub Increment(nBase, nStep) 'some example content 
    nBase = nBase + nStep 
End Sub 
'<Unwonted_Item /> 

Dim source 'reading the same file just for simplification 
With CreateObject("Scripting.FileSystemObject") 
    With .OpenTextFile(WScript.ScriptFullName, 1, False) 
     source = .ReadAll 
    End With 
End With 
result = GetDox(source) 
WScript.Echo result 'display our result 

Function GetDox(sCode) 'unfinished function 
    Dim regEx, Match, Matches, mVal, sEnd 
    sEnd = "</dox>" & vbNewLine 
    Set regEx = New RegExp 
    regEx.Pattern = "('<dox>\n|'\s*<.*)" 'my ugly pattern 
    regEx.IgnoreCase = True 
    regEx.Global = True 
    Set Matches = regEx.Execute(sCode) 
    For Each Match In Matches 
     mVal = Match.Value 
     mVal = Replace(mVal, vbCr, vbNewLine) 
     mVal = Right(mVal, Len(mVal) - 1) 
     GetDox = GetDox & mVal 
     If mVal = sEnd Then Exit For 
    Next 
End Function 

这就是我得到:

<dox> 
    <member type="Public Sub" name="Increment" return="void"> 
    <param type="Integer" name="nBase" out="true" /> 
    <param type="Integer" name="nStep" out="false" /> 
    <purpose> 
    </purpose> 
    </member> 
    <member ... /> 
</dox> 

而这正是我需要的:

<dox> 
    <member type="Public Sub" name="Increment" return="void"> 
    <param type="Integer" name="nBase" out="true" /> 
    <param type="Integer" name="nStep" out="false" /> 
    <purpose> 
     purpose here... 
    </purpose> 
    </member> 
    <member ... /> 
</dox> 

与行 “的宗旨在这里......” 失踪了,我知道,整个RegExp.Pattern语法很薄弱。我只想选择以<dox>开头并以</dox>结尾的整个内容,其中包括所有内容,但我坚持使用模式语法。

P.S.有这么优秀的帮助(感谢所有),这是我现在的工作职能:

Function GetDox(sCode) 
    GetDox = vbNullString 
    With New RegExp 
     .Pattern = "<dox>[\s\S]*?</dox>" 
     .IgnoreCase = True 
     .Global  = False 
     With .Execute(sCode) 
      If .Count = 0 Then Exit Function 
      GetDox = .Item(0).Value 
     End With 
     .Pattern = "^'" 
     .Global  = True 
     .Multiline = True 
     GetDox = .Replace(GetDox, "") 
    End With 
End Function 
+1

为什么你使用正则表达式而不是XPath等? – 2013-03-17 08:40:59

+0

@FrankSchmitt - 我提取了一个绑定在.VBS文件中的XML作为注释,就这些了。 – 2013-03-17 16:16:12

回答

2

我会先移除前导单引号:

regEx.Pattern = "^'" 
regEx.Global = True 
sCode = regEx.Replace(sCode, "") 

然后提取XML文本:

regEx.Pattern = "<dox>[\s\S]*?</dox>" 
regEx.Global = False 
regEx.IgnoreCase = True 
Set m = regEx.Execute(sCode) 
If m.Count > 0 Then GetDox = m(0).Value 

这之后,你应该读取XML成DOM tree作进一步处理:

Set xml = CreateObject("Msxml2.DOMDocument.6.0") 
xml.async = False 
xml.loadXML result 

如果您的XML位于单独的文件中,则应直接从该文件加载XML并使用XPath表达式提取节点,如@FrankSchmitt在其评论中所建议的那样。

Set xml = CreateObject("Msxml2.DOMDocument.6.0") 
xml.async = False 
xml.load "C:\path\to\your.xml" 

Set nodes = xml.selectNodes("//dox") 

XML不是面向行的,不应该像解析一样。如果处理不当,事情可能会以有趣的方式突破。

+0

非常感谢您的详细解答!在调用'.Replace'之前,我设置了'.Multiline = True'来删除单引号。 – 2013-03-17 16:10:52

1

要修复您的代码,你可以使用这个表达式:('<dox>\n|'\s*[\S \t]*)demo

另一种方式来做到这一点会得到你需要的一切先用<dox>[\s\S]+?<\/dox>然后应用取代了它:
搜索:^',无所事事取代

,或者清除前导空格:
搜索:^'\s*的东西就没有更换demo

+0

非常有用,谢谢+1链接! – 2013-03-17 16:05:46