资讯动态

PyLD的IRI解析器详解:相对路径解析与remove_dot_segments算法

发布时间:2026/8/20 18:41:48 来源:尧图企业网站定制
PyLD的IRI解析器详解相对路径解析与remove_dot_segments算法【免费下载链接】pyldJSON-LD processor written in Python项目地址: https://gitcode.com/gh_mirrors/py/pyldPyLD 是一个用 Python 实现的 JSON-LD 处理器负责把 JSON-LD 文档展开expand、压缩compact、扁平化flatten并转换为 RDF。今天我们来聊聊 PyLD 中一个低调却至关重要的组件——IRI解析器重点剖析它的相对路径解析逻辑和 remove_dot_segments 算法看看一条../abc这样的相对 IRI 是如何被精准转换为绝对地址的。为什么 JSON-LD 离不开 IRI 解析器JSON-LD 的本质是用 JSON 表达链接数据而链接数据的世界里一切资源都用IRI国际化资源标识符来定位。在 JSON-LD 文档中context、id、base里经常出现相对路径比如远程上下文用相对 URL 引用文档内部的id写成./people/1词汇表地址带../vocab/这样的回溯段如果这些相对 IRI 不能被正确解析成绝对 IRI展开、规范化normalize等操作得到的 RDF 三元组就会指向错误的资源整个语义数据就对不上号了。PyLD 的 IRI 解析器正是为这个场景量身定做的解决方案。PyLD IRI 解析器在哪里模块结构一览PyLD 的 IRI 解析逻辑被集中放在一个独立模块中方便单独维护和测试核心实现lib/pyld/iri_resolver.py单元测试tests/test_iri_resolver.py根据 CHANGELOG.md这个模块是从context_resolver.py迁移而来并把原先的prepend_base、remove_base函数重命名成了resolve与unresolve。整个模块只依赖 Python 标准库的urllib.parse零第三方依赖非常轻量。模块内一共提供了 6 个函数各司其职函数作用resolve()把相对 IRI 结合 base IRI 解析成绝对 IRIunresolve()逆操作把绝对 IRI 转换为相对 IRIremove_dot_segments()清除路径中的.和..段remove_dot_segments_of_path()只对 IRI 的 path 部分执行清除is_character_allowed_after_relative_path_segment()判断点段后的合法字符parse_authority()解析并去掉默认端口remove_dot_segments 算法路径瘦身的核心remove_dot_segments()是整套解析逻辑的基石它严格遵循 RFC 3986 第 5.2.4 节定义的规范负责把路径中的.当前目录和..上级目录段彻底清除。它原本移植自 JS 生态的 relative-to-absolute-iri 库堪称历经考验的算法。⚙️算法的工作方式逐字符扫描算法用一个循环逐字符扫描路径维护一个段缓冲区列表核心规则如下遇到/..且后面是合法分隔符→ 弹出上一个段返回上级目录遇到/.且后面是合法分隔符→ 忽略当前段留在原目录遇到/→ 开启一个新段遇到?或#→ 查询串或片段原样保留立即停止处理其中合法分隔符由is_character_allowed_after_relative_path_segment()判定只有#、?、/或字符串结尾才允许把./..当作路径段处理——否则它们只是普通文件名的一部分。比如.g是合法文件名不能被误删。典型处理示例把/a/b/c/./../../g传入remove_dot_segments会得到/a/g。过程如下当前段动作a入栈b入栈c入栈.忽略仍在c目录..弹出c..弹出bg入栈边界情况也处理得一丝不苟越界回溯/abc/../../..不会出错而是安全地停在根路径/保留零长度段/abc//def/中的双斜杠不会被破坏不误伤文件名/a/bb/ccc/.g和/a/bb/ccc/g..都保持原样查询与片段不干预/abc?a/../bc中的../属于查询串内容原样保留三段点视为普通段/invalid/...不会被当作..处理这些细节在 tests/test_iri_resolver.py 中都有大量断言覆盖从TestRemoveDotSegments类就能看到几十个边界用例。resolve() 函数相对路径解析的完整流程resolve(relative_iri, base_iri)是相对路径解析的总指挥它按照 RFC 3986 第 5.2 节的参考解析算法组织流程一层层判断代码路径清晰易读。第一步基础预处理若 base 带#fragment先去掉 fragment相对 IRI 为空 → 直接返回 base相对 IRI 以?开头 → 拼接到 base并替换掉 base 原有的查询串相对 IRI 以#开头 → 直接拼接为 base 片段第二步判断独立情况base 为空但相对 IRI 本身含:即自带 scheme→ 视为绝对 IRI直接返回相对 IRI 含:→ 它是绝对 IRI忽略 base这两种情况都会调用remove_dot_segments_of_path()顺手清理路径中的点段。第三步按相对路径形态分派以//开头协议相对→ 继承 base 的 scheme以/开头绝对路径→ 替换 base 的整个路径其他相对路径→ 与 base 路径的最后一个/之后的部分拼接最后统一调用remove_dot_segments()收尾。来看看几个直观的例子from pyld.iri_resolver import resolve # 普通相对路径 resolve(abc, http://base.org/) # http://base.org/abc # 带点段 resolve(../g, file:///a/bb/ccc/d;p?q) # file:///a/bb/g # 绝对路径替换 resolve(/g, file:///a/bb/ccc/d;p?q) # file:///g # 协议相对 resolve(//abc, http://base.org/) # http://abc值得一提的还有异常保护当传入的 base IRI 本身不合法如缺少 scheme 的defresolve()会抛出带明确信息的ValueError方便开发者快速定位问题。unresolve()把绝对 IRI 变回相对路径压缩compact是 JSON-LD 的常用操作它需要把绝对 IRI 重新压缩成更短的相对形式——这正是unresolve()的用武之地。它先通过urllib.parse拆解两个 IRI比较 scheme 和 authority并自动剥离http:80、https:443这类默认端口只有完全匹配时才做相对化处理。随后删除两边路径中相同的公共前缀用../补齐差异最后用urlunparse组装结果from pyld.iri_resolver import unresolve unresolve(http://base.org/abc, http://base.org/) # abc unresolve(http://base.org/#abc, http://base.org/) # #abc unresolve(http://base.org/abc, http://base.org/) # ./abc注意最后一行如果相对 IRI 以开头会被误认为 JSON-LD 关键字会自动加上./前缀规避歧义这个细节体现了 JSON-LD 规范特有的严谨。IRI 解析器在 PyLD 中的真实应用场景这个解析器可不是纸上谈兵它在 PyLD 的多个核心流程中扮演着关键角色上下文解析context_resolver.py 第 122 行用iri_resolver.resolve(url, base)把远程context的相对 URL 解析为绝对地址再执行加载与缓存IRI 压缩jsonld.py 第 5381-5383 行在压缩时调用unresolve(iri, resolve(active_ctx[base], base))把绝对 IRI 压缩成相对于base的短形式文档加载器documentloader/aiohttp.py 与 documentloader/requests.py 都用它计算加载文档的documentUrl全局 base 配置通过 options.py 中的base选项调用方可以显式指定解析基准换句话说从展开到压缩从加载远程上下文到生成 documentUrl处处都有 IRI 解析器的身影。结语小而美的标准实现PyLD 的 IRI 解析器虽然只有约 300 行代码却完整实现了 RFC 3986 的相对路径解析算法并针对 JSON-LD 场景做了贴心适配。理解了remove_dot_segments算法和resolve()的分派逻辑你就掌握了 JSON-LD 世界里地址如何被规范化的核心秘密——下次调试 JSON-LD 处理结果时遇到路径对不上的情况不妨先想想是不是点段处理出了问题。如果你也想亲手运行 PyLD 的 IRI 解析器参考 installation.md 安装后在项目根目录执行pytest tests/test_iri_resolver.py -v就能看到全套解析用例的通过情况了。【免费下载链接】pyldJSON-LD processor written in Python项目地址: https://gitcode.com/gh_mirrors/py/pyld创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价