Office VBA开发经典:中级进阶卷
上QQ阅读APP看书,第一时间看更新

4.6 定位节点

其实,学习XML的DOM对象模型,就是为了更方便地对节点进行定位、读取和修改等操作。由于XML是一个树状结构,节点之间有的是并列关系,有的是所属关系,准确定位到某一节点,通常有很多种方法。以下介绍常用的定位方法。

4.6.1 使用ChildNodes定位所有子节点

XML文件中的一个节点所包含的子节点用ChildNodes集合对象表示。xx.ChildeNodes(0)就表示xx节点的首个子节点。

仍然以“西南省份.xml”为例,该文档对象直属子节点有3个,即处理指令节点、注释节点和根元素节点。XML代码如下。

下面的过程遍历文档对象的所有子节点(只包括直属子节点,不包括孙节点等)。

代码分析:由于各个子节点的类型不一样,因此代码中的对象变量ND需要声明为通用类型.IXMLDOMNode,而不能是IXMLDOMElement。

运行上述过程,在立即窗口打印各子节点的名称、类型和值,如图4-9所示。

图4-9 遍历子节点

需要注意的是,在VBA中DOM对象模型的集合都是以0作为第一个子成员的下标。此外,节点下面的FirstChild也可以定位到第一个子节点,它等价于ChildNodes(0),相对应地,LastChild可以定位到最后一个子节点。

4.6.2 使用PreviousSibling和NextSibling定位前后节点

PreviousSibling与NextSibling表示与节点并列的其他节点,分别表示前一个节点和后一个节点。

“西南省份.xml”中的根元素节点是<Country>,该节点下面包含4个子节点,分别是注释节点和3个元素节点。下列过程用于获取兄弟节点。

代码分析:本例中ND()是一个数组,分别表示3个Province,由于这3个都是元素节点,因此数组的类型可以声明为具体的IXMLDOMElement。

上述程序的运行结果如图4-10所示。

图4-10 获取兄弟节点

4.6.3 使用ParentNode定位父节点

与ChildNodes对应的是ParentNode,ParentNode是指当前节点的上一级节点。由于任一节点的父节点只能是一个,所以该单词后面没有s。

仍然以“西南省份.xml”为例。

在下面的过程中,首先定位到根元素下面的第0个子节点,这是一个注释节点。然后以注释节点为基准,依次回溯其上级节点。

代码分析:ND是一个注释节点,其上级是根元素节点Country,再上一级就是文档对象。

运行上述过程,打印结果如下。

    #comment  Country  #document

注意 如果从XML中的任一节点直接获取根元素节点(祖先节点),可以使用ownerDocument,不需要反复使用ParentNode。

4.6.4 使用XPath定位到任一节点

虽然在实际编程中经常使用ChildNodes定位子节点,但是如果一个XML的嵌套层数非常多,需要多次用到ChildNodes,这时定位就显得麻烦了。

下面介绍使用XPath指定一个路径,从指定节点一步到达定位的深层节点。常用的节点定位的XPath写法如表4-3所示。

表4-3 XPath常用表示形式及其含义

更多XPath的高级用法,请参阅其他资料。

1. 使用SelectSingleNode获取第一个符合路径的节点

下面的过程使用绝对路径的方式查找到第一个名称为Capital的元素节点。

代码分析:/Country/Province/Capital是一个XPath,表示从根元素开始,逐级定位,一直查到Capital为止。虽然本例中的XML文件中有3个Capital节点,但是程序中用的是SelectSingleNode方法,因此找到第一个即可。

运行上述过程,打印结果如下。

    <Capital name="成都"></Capital>

2. 使用SelectNodes获取所有符合路径的节点集合

SelectNodes方法返回的是多个节点构成的集合,因此需要声明为IXMLDOMNodeList类型。

代码分析:对象变量NL获取了多个符合该路径的节点,因此还需要用For循环遍历每个子节点的信息。

运行上述过程,打印结果如下。

    <Capital name="成都"></Capital>
    <Capital name="贵阳"></Capital>
    <Capital name="昆明"></Capital>

4.6.5 使用getElementsByTagName定位到一组元素节点

getElementsByTagName方法是以当前节点为基准,查找指定名称的所有元素节点。

下面的过程从文档对象开始查找所有Population元素节点。

代码分析:这个实例的功能等价于XPath中的//Population。

运行上述过程,打印结果如下。

    <Population Unit="万人">8204</Population>
    <Population Unit="万人">3530</Population>
    <Population Unit="万人">4742</Population>

4.6.6 使用getAttributeNode定位到属性

元素节点的getAttributeNode方法可以定位到元素中的某一属性,返回一个属性节点。

代码分析:代码中的Root是根元素节点(Country),对象变量A是一个属性节点,表示Country元素的name属性。

运行上述过程,打印结果如下。

    name  中国  2

注意 属性一般书写在元素节点的开始标签,但是每一个属性并非元素节点的子节点,因此元素与属性之间的关系不能通过ChildNodes或者ParentNode来描述。

以上内容的源代码文件为“实例文档12.xlsm”。