从XML文件返回所有节点,即使它们是空的

时间:2013-05-22 06:49:23

标签: xml vba msxml

我有一个通过VBA在Access 2010中通过WSDL检索的XML文件。 XML文件位于此变量

Dim xmlDoc As New DOMDocument60

我感兴趣的XML部分如下所示,基本上只为每个UserBean重申一遍。 UserBean基本上是系统中的用户帐户。

<UserBean xsi:type="ns1:UserBean">  
    <primaryKey xsi:type="xsd:string">49084</primaryKey>  
    <updateIndex xsi:type="xsd:int">14</updateIndex>  
    <deleted xsi:type="xsd:boolean">false</deleted>  
    <loginID xsi:type="xsd:string">61420313556</loginID>  
    <name xsi:type="xsd:string">Andrew Mills</name>    
    <teams xsi:type="soapenc:Array" soapenc:arrayType="xsd:string[1]">  
        <string xsi:type="xsd:string">Maintenance</string>  
    </teams>  
    <timezone xsi:type="xsd:string">Australia/Brisbane</timezone>  
    <userTypePK xsi:type="xsd:string">3776</userTypePK>  
    <description xsi:type="xsd:string"/>  
    <emailAddress xsi:type="xsd:string"/>  
    <phoneNumber xsi:type="xsd:string"/>  
    <faxNumber xsi:type="xsd:string"/>  
    <pagerNumber xsi:type="xsd:string"/>  
    <mobileNumber xsi:type="xsd:string">61420313556</mobileNumber>  
    <securityQuestion xsi:type="xsd:string">__INVALID</securityQuestion>  
    <securityAnswer xsi:type="xsd:string"/>  
    <synchronisation xsi:type="soapenc:Array" soapenc:arrayType="ns2:SynchronisationBean[0]" xmlns:ns2="http://soap2.nads.econz.co.nz"/>  
</UserBean>

问题在于并非每个字段都必须填写 因此一些节点没有数据
在VBA中使用MSXML2库仅在其中存在实际文本时才返回节点。 因此,下面的代码将返回可变数量的节点,具体取决于每个userbean包含的内容。例如,某些用户没有填充mobileNumber。

Set nodes xmlDoc.selectNodes("//UserBean")
For Each node in nodes  
    debug.print node.text  
next node

上面的代码返回一个长字符串,其中包含其中所有子节点的所有值(相对于Userbean节点),但只返回具有文本的那些节点。我试图把它放到Access的一个表中,如果有些节点在某些时候丢失了,我就无法跟踪它了......还是我?

如何填充所有节点,无论它们是否已填充 OR
如何识别包含文本的节点的名称,以便知道将值放入Access的表中的哪个位置?

更新
继续下面的评论,我所追求的是一个Userbeans列表,它们本身就是一个列表......所以实际上我是在列表列表之后......所以考虑到这一点我尝试了以下但是它在第一个For Each循环失败了。显然,循环类型无法使用列表作为另一个列表的计数器。有没有解决的办法?

Dim node As MSXML2.IXMLDOMNode
Dim userbeans As MSXML2.IXMLDOMNodeList
Dim userbean As MSXML2.IXMLDOMNodeList

Set userbeans = xmlDoc.selectNodes("//UserBean")
For Each userbean In userbeans '**Type mismatch error here**
    For Each node In userbean
          Debug.Print node.nodeName & ":" & node.Text
    Next node
Next userbean

1 个答案:

答案 0 :(得分:4)

  

我所追求的是Userbeans列表,它们本身就是一个列表

你需要考虑“节点”,而不是“列表”。 selectNodes返回一个指向一组节点的指针,但是当你遍历它时,你最终会得到一个IXMLDOMNode,而不是一个节点列表。您只能通过调用方法来获取nodeList,例如selectNodes。

您可以再次调用selectNodes ,或者只使用IXMLDOMNode的childNodes属性Documented at MSDN

Dim userBeanList As MSXML2.IXMLDOMNodeList
Dim userbean As MSXML2.IXMLDOMNode
Dim beanChild As MSXML2.IXMLDOMNode

Set userBeanList = xmlDoc.selectNodes("//UserBean")
For Each userBean In userBeanList 
    For Each beanChild In userBean.childNodes
          Debug.Print beanChild.nodeName & ":" & beanChildText
    Next beanChild
Next userBean

请注意,使用正确的XPath查询,您只需选择符合条件的节点列表即可。由于这是VBA,你可以跳过显式声明,除非你要利用智能感知。

dim badNodes, badNode
set badNodes = xmlDoc.selectNodes("//UserBean/*[not(text())]")
if badNodes.length < 1 then
  debug.Print "All good!"
else
  debug.Print "following nodes are empty:"
  For Each badNode in badNodes
    debug.print " - " & badNode.name
  next badNode
endif