2013-10-11 19 views
0

考慮下面的XML我怎樣才能提取所有子節點與通用文本值

<Tests> 
    <AutomatedTests> 
     <TestName>Test1</TestName> 
     <FunctionalLibraries> 
      <FunctionalLibrary>CommonLib</FunctionalLibrary> 
      <FunctionalLibrary>AppTestLib</FunctionalLibrary> 
      <FunctionalLibrary>Test1Lib</FunctionalLibrary> 
     </FunctionalLibraries> 
    </AutomatedTests> 
    <AutomatedTests> 
     <TestName>Test2</TestName> 
     <FunctionalLibraries> 
      <FunctionalLibrary>CommonLib</FunctionalLibrary> 
      <FunctionalLibrary>AppTestLib</FunctionalLibrary> 
      <FunctionalLibrary>Test2Lib</FunctionalLibrary> 
     </FunctionalLibraries> 
    </AutomatedTests> 
    <AutomatedTests> 
     <TestName>Test3</TestName> 
     <FunctionalLibraries> 
      <FunctionalLibrary>CommonLib</FunctionalLibrary> 
      <FunctionalLibrary>Test3Lib</FunctionalLibrary> 
     </FunctionalLibraries> 
    </AutomatedTests> 
</Tests> 

使用VBScript,我如何才能找到通用於所有的/測試所有/測試/ AutomatedTests/FunctionalLibraries節點/ AutomatedTests節點。
基於上述XML,結果應該是...

<CommonTestLibraries> 
    <FunctionalLibrary>CommonLib</FunctionalLibrary> 
</CommonTestLibraries> 

感謝

這裏是我有什麼,我希望有一個更簡單的方法,因爲我必須在做這幾次同一個文件。

set tempDict = CreateObject("Scripting.Dictionary") 
set commonDict = CreateObject("Scripting.Dictionary") 

Set xmlDoc = CreateObject("Microsoft.XMLDOM") 
xmlDoc.Load(fileName) 
set testNodes = xmlDoc.SelectNodes("/Tests/AutomatedTests") 
isFirst = true 

for each testNode in testNodes 
    set functionalLibraryNodes = testNode.SelectNodes("FunctionLibraries/FunctionLibrary") 
    For Each functionalLibraryNode in functionalLibraryNodes 
     If not tempDict.Exists(functionalLibraryNode.Text) Then 
      tempDict.Add functionalLibraryNode.Text, functionalLibraryNode.Text 
     End If 
    Next 
    If NOT isFirst Then 
     for each item in commonDict 
      if tempDict.Exists(item) = false Then 
       commonDict.Remove item 
      End If 
     Next 
    Else 
     Set commonDict = tempDict 
     isFirst = false 
    End If 

    Set tempDict = nothing 
    Set tempDict = CreateObject("Scripting.Dictionary") 
Next 
+0

你看過嗎? http://stackoverflow.com/questions/14975608/recurse-xml-file-using-vbscript – Leptonator

+1

SO不是一個「爲我自由寫代碼」類型的網站。你試過什麼了? –

+0

@Leptonator,您建議的鏈接似乎不符合我的要求。 – bthound

回答

0

作爲 '共同' 的lib出現n次n的測試中,詞典的方法可以更簡單:

Dim oFS : Set oFS = CreateObject("Scripting.FileSystemObject") 
    Dim sFSpec : sFSpec = oFS.GetAbsolutePathName("..\data\02.xml") 
    Dim oXML : Set oXML = CreateObject("Msxml2.DOMDocument.6.0") 
    oXML.load sFSpec 
    If 0 = oXML.parseError Then 
    Dim sXPath : sXPath  = "/Tests/AutomatedTests/FunctionalLibraries/FunctionalLibrary" 
    Dim ndlFnd : Set ndlFnd = oXML.selectNodes(sXPath) 
    If 0 = ndlFnd.length Then 
     WScript.Echo sXPath, "not found" 
    Else 
     Dim dicLibs : Set dicLibs = CreateObject("Scripting.Dictionary") 
     Dim nTests : nTests  = ndlFnd(0).parentNode.parentNode.parentNode.childNodes.length 
     WScript.Echo nTests, "tests" 
     Dim ndFnd, sLib 
     For Each ndFnd In ndlFnd 
      sLib = ndFnd.text 
      dicLibs(sLib) = dicLibs(sLib) + 1 
     Next 
     For Each sLib In dicLibs.Keys() 
      If dicLibs(sLib) = nTests Then 
       WScript.Echo sLib, dicLibs(sLib) 
      End If 
     Next 
    End If 
    Else 
    WScript.Echo oXML.parseError.reason 
    End If 
1

我可能會做這樣的事情:

filename = "C:\path\to\your.xml" 

Set xmlDoc = CreateObject("Msxml2.DOMDocument.6.0") 
xmlDoc.async = False 
xmlDoc.load filename 

If xmlDoc.parseError <> 0 Then 
    WScript.Echo xmlDoc.parseError.reason 
    WScript.Quit xmlDoc.parseError 
End If 

'determine the total number of tests 
numTests = xmlDoc.selectNodes("/Tests/AutomatedTests").length 

'count the libraries from all tests 
Set commonDict = CreateObject("Scripting.Dictionary") 
For Each node In xmlDoc.selectNodes("//FunctionalLibrary") 
    commonDict(node.text) = commonDict(node.text) + 1 
Next 

'libraries common to all tests must have occurred {numTests} number of times 
For Each lib In commonDict.Keys 
    If commonDict(lib) = numTests Then WScript.Echo commonDict(lib) 
Next 

雖然可能有更有效的方法。

注:

commonDict(node.text) = commonDict(node.text) + 1 

利用以下事實,即一個表達式dict(key)自動添加一個不存在的鍵,字典和一個空值進行初始化。然後該空值在添加中被轉換爲0。用相同的語義明確的代碼是這樣的:

If Not commonDict.Exists(node.text) Then 
    commonDict(node.text) = 0 
Else 
    commonDict(node.text) = commonDict(node.text) + 1 
End If 

注: XPath表達式//FunctionalLibrary將選擇從XML樹中的任何地方FunctionalLibrary節點。如果您有任何這樣的節點即是直接子節點/Tests/AutomatedTests/FunctionalLibraries(您提供的樣本數據表明你沒有),你應該做的XPath表達式明確:

funclib = "/Tests/AutomatedTests/FunctionalLibraries/FunctionalLibrary" 
For Each node In xmlDoc.selectNodes(funclib) 
    commonDict(node.text) = commonDict(node.text) + 1 
Next 
+1

很好,+1;但'WScript.Quit xmlDoc.parseError'應該使用'WScript.Quit xmlDoc.parseError.errorCode'或一個合適的常量,我認爲「// FunctionalLibrary」 - 所有以「//」開頭的XPathes都是有風險的。 –

+0

'errorCode'是'parseError'對象的默認屬性,所以'xmlDoc.parseError'和'xmlDoc.parseError.errorCode'是相同的。至於在XPath查詢中使用// //:是的,當XML包含不是'/ Tests/AutomatedTests/FunctionalLibraries'的直接子節點的'FunctionalLibrary'節點時,該查詢可能會產生假結果。但是,樣本數據並不表明這種情況。我會在我的答案中添加一個註釋。 –

+0

我喜歡這種方法。只使用一個字典可以更容易管理。至於'添加一個不存在的密鑰'的說明,我不知道這一點,謝謝你。 – bthound