章节摘要:真实 XML 很少像书店样本那样「裸名就能选中」。默认命名空间会让
/bookstore/book变成空集。本章动手优先:先把前缀绑到 URI 上写出能命中的路径,再谈 2.0 变量、自定义函数,以及类型与 Schema。前缀是本地别名,匹配看 URI。
阅读完本章,你应当能够:
xmlns 看起来像属性却不能用 @xmlns 去匹配元素金句:名字相同只是贴纸相同;海关认的是护照 URI。

默认命名空间、带前缀声明、查询侧注册映射。local-name()='book' 能应急,但会误伤其他词汇里的同名元素。
XPath 2.0 的 $x、let、外部从宿主注入。自定义函数多在 XSLT/XQuery 里声明,纯 1.0 路径没有「def」。
1.0 只有节点集、布尔、数字、字符串。2.0 原子类型和 Schema 导入让 price 真的是小数。没有 Schema 时继续 number()。
命名空间是实战第一阻塞。变量是把已能跑的路径收干净。类型是让比较诚实。
3.1 绑前缀让路径重新命中 │ ▼ 3.2 用变量和函数收重复 │ ▼ 3.3 有 Schema 就让类型替 number 干活
按原文集顺序,变量和自定义函数排在命名空间前面。动手优先的读者会先撞上「路径和昨天一模一样,今天换了份带 xmlns 的报文就空了」。所以本章把护照问题提前。变量和 Schema 是已经能选中之后的整理工具,解决不了选不中。
默认命名空间是最大的陷阱:源码里元素名仍叫 bookstore,看不见前缀,查询却必须绑一个前缀。只给最后一步加前缀不够,祖先也在同一个默认空间里,第一步就会空。属性通常不进默认空间,category 继续用 at 选取。这些规则 3.1 会反复练。
| 节 | 动手任务 | 1.0 能否完成 |
|---|---|---|
| 3.1 | 给默认空间文档注册前缀并选出 book | 能,靠宿主映射 |
| 3.2 | 把价格阈值变成外部变量 | 1.0 用宿主拼接或后过滤 |
| 3.3 | 判断有无 Schema 时价格怎么比 | 无 Schema 继续 number |
local-name 等于 book 能应急翻墙,也会把另一套词汇里的同名元素混进来。能注册前缀就不要长期靠 local-name。URI 看起来像网址但不必能打开,打开 404 不代表你写错了护照号。第 4 章会演示 lxml 的 namespaces 字典和 Java 的上下文接口,本章先把「为什么必须绑」讲清,避免到了 API 层还在猜前缀要不要和源码一致——不必一致,URI 一致即可。
命名空间空结果的外表和「元素名写错」完全一样:都是零节点。所以调试必须先打 local-name 和 namespace-uri,而不是先改轴。默认空间让源码看起来还是 bookstore,查询侧却必须带前缀,而且每一层都要带。只给最后一步加前缀,第一步就空。属性通常不进默认空间,category 继续 at 选取。这三句话能处理真实报文里八成的命名空间事故。
变量和自定义函数在 1.0 里不是路径语法能解决的。阈值放宿主,重复路径放 Python 函数,等引擎真的是 2.0 再 let。Schema 文件放在旁边不会让 lxml 按小数比较价格。类型注解要 schema-aware 引擎才看得见。本章不把 2.0 和 Schema 当必学高潮,它们是「已经能选中之后」的整理工具。选不中时回去 3.1,不要在 3.2 的 let 里找原因。
护照比喻贯穿本章:前缀是贴纸,URI 是护照号,海关认护照。URI 打不开网页不说明写错。local-name 应急会误伤其他词汇的同名元素。能注册映射就注册。第 4 章会演示字典怎么传,本章先把「为什么必须传」钉死,否则 API 层仍会有人猜前缀要不要和源码一致——不必一致。
真实报文很少像书店样本那样裸名就能中。默认空间让源码看不见贴纸,查询却必须一层层贴。变量和说明书是选中之后的整理,解决不了选不中。调试空结果先打本地名和护照号。贴纸可与源码不同,护照号必须同。轻量库不会因为旁边放着说明书就把价格当成小数。本章把护照问题提前,是动手优先对原文顺序的调整。过不了第一节不要在绑定语法里找原因。
真实报文很少像书店样本那样裸名就能中。默认空间让源码看不见贴纸,查询却必须一层层贴,只给最后一步贴,第一步就空。贴纸可以和源码不一致,护照号必须一致,打不开网页不说明写错。属性通常不进默认空间,分类盖章继续按属性取。本地名应急会误伤其他词汇的同名标签。变量和说明书是已经能选中之后的整理工具,解决不了选不中;轻量库也不会因为旁边放着说明书就把价格当成小数。调试空结果先打本地名和护照号,不要先改方向。本章把护照问题提前,是动手优先对原文顺序的调整。过不了第一节不要在绑定语法里找原因。