在XPath解析XML或HTML文档的过程中,提取节点文本是高频操作,其中string()函数和.都常被用于获取文本内容,但两者的底层逻辑和返回结果存在明显差异,理解这些差异能避免很多解析错误。

基础定义与核心差异
首先我们需要明确两者的基本定义:
- . 是XPath中的上下文节点简写,它的返回值是当前选中的节点本身,当用在需要字符串的上下文时,会自动将节点转换为字符串,转换规则是获取节点的字符串值。
- string() 是XPath内置的字符串转换函数,它的参数是节点或节点集,返回值是将参数转换为字符串的结果,转换规则同样是获取节点的字符串值。
从定义上看,两者在单节点无嵌套的场景下返回结果一致,但在多节点、嵌套节点的场景下表现完全不同。
单节点场景下的表现
当XPath表达式选中的是单个节点,且节点没有子节点时,两者的返回结果完全相同。比如我们有以下XML文档:
<book>
<title>XPath教程</title>
</book>
使用以下两个XPath表达式提取title节点的文本:
//title/. //title/string()
两者都会返回字符串XPath教程,此时没有差异。
多节点选中的场景差异
当XPath表达式选中的是多个节点时,两者的表现会出现明显不同。我们修改XML文档如下:
<bookstore>
<book>
<title>XPath教程</title>
</book>
<book>
<title>XML基础</title>
</book>
</bookstore>
此时使用//title/.表达式,返回的是两个title节点组成的节点集,不同XPath解析器的处理方式不同,部分解析器只会返回第一个节点的字符串值,部分会直接报错。而使用string(//title)表达式,XPath规范规定,当string()函数的参数是节点集时,只会返回节点集中第一个节点的字符串值,也就是XPath教程。
我们可以通过Python的lxml库来验证这个差异,示例代码如下:
from lxml import etree
xml_content = """
<bookstore>
<book>
<title>XPath教程</title>
</book>
<book>
<title>XML基础</title>
</book>
</bookstore>
"""
tree = etree.XML(xml_content.encode())
# 使用.提取
dot_result = tree.xpath('//title/.')
print("使用.的结果类型:", type(dot_result))
print("使用.的结果:", dot_result)
# 使用string()提取
string_result = tree.xpath('string(//title)')
print("使用string()的结果类型:", type(string_result))
print("使用string()的结果:", string_result)
运行上述代码,输出结果如下:
使用.的结果类型: <class 'list'> 使用.的结果: [<Element title at 0x7f8a1c2d3d40>, <Element title at 0x7f8a1c2d3e80>] 使用string()的结果类型: <class 'str'> 使用string()的结果: XPath教程
可以看到,.返回的是节点列表,而string()直接返回了第一个节点的字符串内容。
嵌套节点场景下的差异
当节点存在嵌套子节点时,两者的文本拼接规则也有区别。我们看如下XML文档:
<p>
第一段内容
<em>强调内容</em>
第二段内容
</p>
使用string(//p)表达式,会将p节点下所有文本节点的内容拼接起来,返回第一段内容强调内容第二段内容。而使用//p/.表达式,返回的是p节点本身,当转换为字符串时,同样会拼接所有子文本节点的内容,此时结果和string()一致。
但如果我们需要分别获取p节点下的不同部分文本,就需要用不同的方式。比如要获取em标签前的文本,可以使用//p/text()[1],要获取em标签后的文本,可以使用//p/text()[2],此时.和string()都无法直接满足需求。
使用场景总结
根据上述对比,我们可以总结出两者的适用场景:
| 场景 | 推荐使用 | 原因 |
|---|---|---|
| 提取单个节点的完整拼接文本 | 两者均可 | 返回结果一致 |
| 提取多个节点中第一个节点的文本 | string() | 直接返回字符串,无需额外处理节点集 |
| 需要获取节点本身进行后续操作 | . | 返回的是节点对象,可进一步提取属性、子节点等 |
| 处理嵌套节点的文本拼接 | string() | 自动拼接所有子文本节点,无需手动处理 |
注意:不同XPath解析器对.的处理可能存在细微差异,在需要稳定获取字符串结果的场景下,优先使用string()函数更稳妥。
XPathstring()函数节点文本提取XML解析HTML解析修改时间:2026-07-19 11:39:25