XPath 1.0如何仅提取根到叶路径上各节点的元素名称,不含子内容
问题根因
你直接输出ancestor-or-self轴返回的节点对象时,XML节点的默认序列化逻辑会输出节点的完整内容(包含所有子节点),只需对返回的节点集合单独提取名称属性再拼接即可满足需求。
实现方案
以下适配你使用的Smalltalk XMLParser库,两种实现方式可选:
方案1:基于XPath实现
先定位目标节点,再通过XPath获取路径节点并拼接:
| targetNode pathNodes pathString | "1. 定位目标节点:对应<author>Erik T. Ray</author>" targetNode := doc xpath: '//book[title/text() = "Learning XML"]/author' first. "2. 获取当前节点到根节点的所有元素节点" pathNodes := targetNode xpath: 'ancestor-or-self::element()'. "3. 反转顺序为根到叶,提取节点名拼接为要求格式" pathString := '' join: (pathNodes reversed collect: [:node | '<', node qualifiedName, '>']).
执行后pathString的输出就是你需要的 <bookstore><book><author>
方案2:基于DOM API遍历(性能更优)
不需要执行XPath查询,直接遍历节点父链即可:
| currentNode pathParts pathString | "1. 定位目标节点" targetNode := doc xpath: '//book[title/text() = "Learning XML"]/author' first. currentNode := targetNode. pathParts := OrderedCollection new. "2. 从当前节点向上遍历父节点,收集节点名" [currentNode notNil and: [currentNode isElement]] whileTrue: [ pathParts addFirst: '<', currentNode qualifiedName, '>'. currentNode := currentNode parent. ]. "3. 拼接为最终路径" pathString := '' join: pathParts.
扩展说明
- 如果你需要标准XPath路径格式(用斜杠分隔,无尖括号),把拼接逻辑里的
<、>去掉,改用/做连接符即可,得到bookstore/book/author格式的输出 - 如果需要区分同名同级节点(比如多本book节点的路径),可以在收集节点名时拼接位置谓词:
node qualifiedName, '[', (node precedingSiblingNodesSelect: [:n | n name = node name]) size + 1 asString, ']',就能得到bookstore/book[4]/author的带位置路径
内容的提问来源于stack exchange,提问作者gettimothy
相关产品推荐
相关产品推荐

