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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16685190/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-11 21:14:33  来源:igfitidea点击:

Return all nodes from XML file, even when they are empty

xmlvbamsxml

提问by zoonosis

I have an XML file retrieved via WSDL in Access 2010 via VBA. The XML file is sitting in this variable

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

Dim xmlDoc As New DOMDocument60

The part of the XML I'm interested in looks like the below and basically just reiterates itself for every UserBean. A UserBeanis basically a user account in a system.

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

<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>

The problem is that not every field is mandatory to be filled in.
Therefore some nodes have no data
Using the MSXML2 library in VBA only returns nodes if there is actually text in it. Therefore the code below will return a variable amount of nodes depending on what each userbean contains. For example some users dont have a mobileNumber populated.

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

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

The above code returns a long string that has all of the values of all of the child nodes in it (with respect to the Userbeannode), but only the ones that have text. I'm trying to get this into a table in Access and if some of the nodes are missing some of the time, I've got no way of tracking it... or do I?

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

How do I return ALL nodes whether they are populated or not
OR
How do I identify the name of the node that has the text so I know where to put the value into the table in Access?

如何将所有节点返回它们是否被填充与否

如何识别具有文本节点的名称,所以我知道放在哪里值到表中的访问?

UPDATE
Further to the below comments, what i'm after is a list of Userbeans, which are in themselves a list...so in fact i'm after a list of lists...so with that in mind I tried the below but it failed at the first For Eachloop. Obviously that type of loop can't handle using lists as a counter for another list. Is there a way around this?

更新
除了下面的评论之外,我所追求的是一个 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

回答by DougM

what i'm after is a list of Userbeans, which are in themselves a list

我想要的是一个 Userbeans 列表,它们本身就是一个列表

You need to think in terms of "nodes", not "lists." selectNodesreturns a pointer to a set of nodes, but when you iterate through it you wind up with an IXMLDOMNode, not a Node List. You can only get a nodeList by calling a method, such as selectNodes.

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

You can to call selectNodes again, or just use the IXMLDOMNode's childNodesproperty, Documented at MSDN

您可以再次调用 selectNodes ,或者只使用 IXMLDOMNode 的 childNodes属性,文档在 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

Note that with a proper XPath Query, you can just select a list of nodes that meet your criteria. And since this is VBA, you can skip the explicit declarations unless you're going to take advantage of the intellisense.

请注意,使用适当的 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