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