Xmllint

← 返回目录 > ← 返回总览

相关工具推荐

工具 说明
Prettier 可通过 prettier-plugin-xml 支持 XML 格式化
Markdownlint 标记语言检查工具
Pre-commit Git 提交门禁框架

1. 简介

xmllint 是 GNOME libxml2 项目提供的命令行 XML 处理工具,广泛用于 XML 文件的格式合法性验证(well-formedness)、DTD 校验、XML Schema(XSD)校验、RelaxNG 校验、Schematron 校验、XPath 查询和格式化输出。它不是独立发布的工具仓库,而是随 libxml2 一起构建和发布,在 Linux 发行版、macOS 和类 Unix 环境中通常通过系统包管理器安装。

  • 主要检查语言:XML、XHTML、SVG、MathML
  • 主要检查能力:XML well-formedness 格式合法性检查、DTD/XSD/RelaxNG/Schematron 验证、XPath 表达式查询、XML 格式化输出、HTML 容错解析、命名空间清理、XInclude 处理;涵盖验证类检查(格式合法性、DTD/XSD 结构验证)+ 格式化类检查(XML 重新排版)
  • 核心检查原理:基于 libxml2 C 库的流式解析
  • 检查规则/选项:约 60+ 个命令行选项(分为验证、解析器、输出、调试/杂项 4 大类),支持 DTD/XSD/RelaxNG/Schematron 验证,全量选项说明
  • GitHub 仓库:N/A(libxml2 子项目,https://gitlab.gnome.org/GNOME/libxml2)
  • 开源协议:MIT
  • 最新稳定版本:v2.15.3(libxml2 版本)
  • 运行环境要求:需 libxml2 运行库;随系统包管理器分发
  • 误报率:无

xmllint 是 XML 格式合法性验证领域的基础工具,适合作为 CI/CD 中的基础质量门禁:先保证 XML 可解析、可验证,再按需叠加 Prettier 等格式化工具统一风格。


2. 官方文档

资源 链接 说明
libxml2 仓库(GitLab) https://gitlab.gnome.org/GNOME/libxml2 源码、Issue、Release
libxml2 官方文档站 https://gnome.pages.gitlab.gnome.org/libxml2/ API 文档、各模块说明
xmllint 手册页 https://gnome.pages.gitlab.gnome.org/libxml2/xmllint.html 命令行参数、选项、退出码等完整参考
XML Schema 支持说明 https://gnome.pages.gitlab.gnome.org/libxml2/xmlschemas.html XSD Schema 验证 API
XPath 支持说明 https://gnome.pages.gitlab.gnome.org/libxml2/xpath.html XPath 查询 API
libxml2 Release 列表 https://gitlab.gnome.org/GNOME/libxml2/-/releases 各版本发布说明

3. 社区优秀实践

3.1 pre-commit/pre-commit-hooks

pre-commit-hooks 是 pre-commit 官方维护的通用钩子仓库,其中包含 check-xml 钩子,用于验证 XML 文件的语法合法性。这是 XML 项目中最常见的 pre-commit 集成方案。

  • 仓库地址https://github.com/pre-commit/pre-commit-hooks
  • 实践要点
    • check-xml 钩子使用 Python 内置的 xml.etree.ElementTree 解析 XML 文件,验证格式合法性
    • 当前最新版本为 v6.0.0
    • 适合作为基础 XML 语法检查门禁

3.2 GNOME libxml2 项目自身

libxml2 项目自身在 CI 中大量使用 xmllint 进行测试和验证,包括 XML/HTML 解析测试、Schema 验证测试、XPath 测试等。项目的测试套件和 CI 流水线是 xmllint 各项功能的最佳参考。

3.3 Homebrew

Homebrew 是 macOS 和 Linux 上主流的包管理器,其核心仓库 Homebrew/brew 包含大量 XML 格式的配置文件和资源描述文件。Homebrew 在 CI 流水线中使用 xmllint 对 XML 文件进行质量检查。


4. 工具配置说明

xmllint 是 XML 格式验证和结构验证工具,不是规则驱动的 Linter,没有可配置的规则集。其行为通过命令行参数和环境变量控制。

4.1 配置文件说明

xmllint 本身没有独立的配置文件,通过命令行参数和环境变量配置:

配置方式 说明 使用场景
命令行参数 控制 xmllint 的验证、格式化、查询等行为 所有场景,通过命令行或脚本调用
环境变量 影响 --format 缩进、Catalog 解析等行为 需要自定义缩进或 Catalog 解析的场景

以下环境变量可以影响 xmllint 行为:

环境变量 说明
XMLLINT_INDENT 控制 --format 的缩进字符串,默认为两个空格
XML_CATALOG_FILES 指定 XML Catalog 文件路径列表(空格分隔)
SGML_CATALOG_FILES 指定 SGML Catalog 文件路径列表

4.2 命令行参数详解

xmllint 的核心行为通过命令行参数控制,以下列出常用参数:

参数说明

参数 类型 说明
--noout flag 不输出解析后的 XML,仅检查格式合法性(最常用)
--encode string 指定输出编码(如 UTF-8
--schema string 指定 XSD Schema 文件进行结构验证
--valid flag 使用 DTD 进行验证
--dtdvalid string 指定外部 DTD 文件进行验证
--xpath string 执行 XPath 查询并输出匹配结果
--format flag 格式化输出(美化缩进,受 XMLLINT_INDENT 环境变量影响)
--recover flag 尝试恢复并继续解析错误文档
--html flag 以 HTML 模式解析(容错性更高)
--xinclude flag 处理 XInclude 指令
--c14n flag 输出 XML Canonicalization(C14N)规范形式

推荐使用示例

基础 XML 项目(格式合法性检查):适用于所有包含 XML 文件的项目,确保 XML 文件格式合法、可被正确解析。

# 单文件检查
xmllint --noout file.xml

# UTF-8 编码 + 格式合法性检查
xmllint --noout --encode UTF-8 file.xml

# CI 中批量检查(排除 node_modules 和 .git 目录)
find . -name '*.xml' -not -path './node_modules/*' -not -path './.git/*' \
  -print0 | xargs -0 xmllint --noout

XSD 验证项目(结构验证):适用于有 XML Schema 定义的项目,在格式合法性基础上增加结构验证。

# 使用 XSD Schema 验证单个文件
xmllint --noout --schema schemas/config.xsd config/app.xml

# CI 中批量 XSD 验证
find ./config -name '*.xml' -print0 | \
  xargs -0 xmllint --noout --schema schemas/config.xsd

格式化输出(美化 XML):

# 使用默认缩进(两个空格)格式化
xmllint --format file.xml

# 使用 4 个空格缩进格式化
XMLLINT_INDENT='    ' xmllint --format file.xml

pre-commit 与 CI 的完整集成配置见第 5 章。


5. 主流集成方式

5.1 pre-commit 集成

pre-commit 是 XML 项目中常见的提交门禁方案,pre-commit-hooks 提供了 check-xml 钩子用于基础 XML 语法检查。对于需要更完整验证(如 XSD 校验)的场景,可以使用 language: system 的 local hook 调用本机 xmllint

方式一:使用 pre-commit-hooks 的 check-xml(基础语法检查)

依赖来源与适用前提

  • 使用 language: python,由 pre-commit 自动管理 Python 虚拟环境
  • 无需本地安装额外工具
  • pre-commit 框架默认仅将暂存区中变更文件传给 hook,天然支持增量检查
# .pre-commit-config.yaml
repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v6.0.0
    hooks:
      - id: check-xml

方式二:使用 local hook 调用本机 xmllint(完整验证)

依赖来源与适用前提

  • 使用 language: system,需要系统已安装 xmllint(通常通过 apt install libxml2-utilsbrew install libxml2
  • 适合需要 DTD/XSD 验证等 check-xml 不支持的场景
# .pre-commit-config.yaml
repos:
  - repo: local
    hooks:
      - id: xmllint-validate
        name: xmllint XML 验证
        entry: xmllint --noout --encode UTF-8
        language: system
        types: [xml]
        pass_filenames: true

方式三:按目录配置 XSD 验证

repos:
  - repo: local
    hooks:
      - id: xmllint-xsd
        name: xmllint XSD 验证
        entry: xmllint --noout --schema schema.xsd
        language: system
        files: ^data/.*\.xml$
        pass_filenames: true

增量检查:pre-commit 框架默认仅将暂存区中变更文件传给 hook,天然实现文件级增量检查,无需额外配置。CI 中可通过 pre-commit run --all-files 做全量检查,或使用 --from-ref/--to-ref 做 PR 级增量。

5.2 IDE 集成

VS Code

VS Code 没有广泛使用的 xmllint 专用扩展。对于 XML 文件的实时检查和格式化,社区通常使用以下方案:

  • 安装 Red Hat XML 扩展,提供 XML 语言服务(基于 LSP),支持 XML Schema 验证、格式化、自动补全
  • 安装 Prettier + prettier-plugin-xml 进行 XML 格式化

Vim / Neovim

通过 ALE(异步 Lint 引擎)集成 xmllint

" ~/.vimrc 或 ~/.config/nvim/init.vim
Plug 'dense-analysis/ale'

let g:ale_linters = {
\   'xml': ['xmllint'],
\}
let g:ale_xml_xmllint_options = '--noout'

其他方案:Neomake 也支持 xmllint

IntelliJ IDEA / PyCharm / GoLand

IntelliJ 系列 IDE 内置 XML 语言支持,提供 XML Schema 验证、DTD 验证和格式化功能,无需额外安装 xmllint。对于需要命令行验证的场景,可通过 External Tools 配置调用 xmllint

5.3 系统包管理器安装(生态主流)

xmllint 的主要安装方式是通过系统包管理器,这是 XML 生态中最主流的方式。xmllintlibxml2 库一起安装,包名通常为 libxml2-utils

# Ubuntu / Debian
sudo apt install libxml2-utils

# Fedora / RHEL / CentOS
sudo dnf install libxml2

# Arch Linux
sudo pacman -S libxml2

# macOS
brew install libxml2

# Alpine Linux(常用于 CI 容器)
apk add libxml2-utils

# MSYS2 (Windows)
pacman -S libxml2

# Nix
nix-env -iA nixpkgs.libxml2

注意:不同发行版的包名和提供的工具可能不同。Ubuntu/Debian 的 libxml2-utils 包含 xmllintxmlcatalog;Fedora 的 libxml2 包即包含 xmllint

5.4 命令行使用方式

常用命令

# 验证 XML 是否格式合法(well-formed),无输出通常表示通过
xmllint --noout config.xml

# 检查多个 XML 文件
find . -name '*.xml' -not -path './node_modules/*' -print0 | xargs -0 xmllint --noout

# 从标准输入读取
cat config.xml | xmllint --noout -

常用参数

# 格式化输出到标准输出
xmllint --format document.xml

# 格式化并写入新文件
xmllint --format document.xml > formatted.xml

# DTD 验证(使用文档内嵌的 DTD)
xmllint --noout --valid document.xml

# 使用指定 DTD 文件验证
xmllint --noout --dtdvalid rules.dtd document.xml

# XSD Schema 验证
xmllint --noout --schema schema.xsd document.xml

# RelaxNG 验证
xmllint --noout --relaxng schema.rng document.xml

# Schematron 验证
xmllint --noout --schematron schema.sch document.xml

# XPath 查询
xmllint --xpath '//title/text()' document.xml

# 指定编码输出
xmllint --encode UTF-8 --noout document.xml

# 尝试恢复损坏的 XML(适合排查问题,不建议作为严格 CI 门禁)
xmllint --recover --noout broken.xml

# 清理冗余命名空间声明
xmllint --nsclean --noout document.xml

# 流式解析(适合大文件)
xmllint --stream --noout --valid huge.xml

# 不加载外部网络资源
xmllint --nonet --noout document.xml

# 显示版本号
xmllint --version

退出码说明

xmllint 的退出码可用于脚本化判断:

退出码 含义
0 无错误
1 未分类错误
2 DTD 错误
3 验证错误
4 文档格式不合法或无法读取
5 Schema 编译错误
6 输出写入错误
9 内存不足
10 XPath 求值错误
11 XPath 结果为空

完整退出码说明参见:xmllint 手册页 - DIAGNOSTICS

增量检查xmllint 没有原生的增量检查参数,但支持通过命令行传入多个文件路径和从标准输入读取,可结合 git diff 筛选变更文件实现增量检查:

# 传入多个文件
xmllint --noout file1.xml file2.xml file3.xml

# 从标准输入读取
cat file.xml | xmllint --noout -

# 仅检查暂存区(staged)中新增或修改的 .xml 文件
git diff --cached --name-only --diff-filter=ACMR -- '*.xml' | xargs -r xmllint --noout

# 仅检查当前分支相对 main 变更过的 .xml 文件
git diff --name-only --diff-filter=ACMR origin/main...HEAD -- '*.xml' | \
  xargs -r xmllint --noout

# 仅检查工作区中修改的 .xml 文件
git diff --name-only --diff-filter=ACMR -- '*.xml' | xargs -r xmllint --noout

--diff-filter=ACMR 表示仅包含新增(A)、复制(C)、修改(M)、重命名(R)的文件,排除删除的文件。-r 参数(GNU xargs)表示当输入为空时不执行命令。

CI 脚本调用:在 CI 环境中通过脚本调用 xmllint 进行 XML 格式验证。

GitHub Actions

方式一:使用系统包管理器

name: XML Quality
on: [push, pull_request]
jobs:
  xml:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: 安装 xmllint
        run: sudo apt update && sudo apt install -y libxml2-utils

      - name: 验证 XML 格式合法性
        run: |
          find . -name '*.xml' \
            -not -path './node_modules/*' \
            -not -path './.git/*' \
            -print0 | xargs -0 xmllint --noout

方式二:使用 Alpine 镜像(更轻量)

name: XML Quality
on: [push, pull_request]
jobs:
  xml:
    runs-on: ubuntu-latest
    container: alpine:latest
    steps:
      - uses: actions/checkout@v4

      - name: 安装 xmllint
        run: apk add libxml2-utils

      - name: 验证 XML 格式合法性
        run: |
          find . -name '*.xml' \
            -not -path './node_modules/*' \
            -not -path './.git/*' \
            -print0 | xargs -0 xmllint --noout

GitLab CI

xml-check:
  stage: test
  image: alpine:latest
  before_script:
    - apk add libxml2-utils
  script:
    - |
      find . -name '*.xml' \
        -not -path './node_modules/*' \
        -not -path './.git/*' \
        -print0 | xargs -0 xmllint --noout

增量检查:GitHub Actions 中仅检查 PR 变更的 XML 文件:

- name: 检查变更的 XML 文件
  run: |
    git diff --name-only --diff-filter=ACMR \
      ${{ github.event.pull_request.base.sha }}...${{ github.sha }} \
      -- '*.xml' | xargs -r xmllint --noout

GitLab CI 中按 MR 变更文件触发增量检查:

xml-check:
  stage: test
  image: alpine:latest
  before_script:
    - apk add libxml2-utils
  script:
    - git diff --name-only --diff-filter=ACMR $CI_MERGE_REQUEST_DIFF_BASE_SHA...HEAD -- '*.xml' | xargs -r xmllint --noout
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"

6. 告警抑制(屏蔽)方法

xmllint 的主要职责是 XML 解析与标准验证,不支持像代码 Linter 那样通过注释逐行屏蔽某条规则。常见"抑制"方式是缩小检查范围、选择不同验证模式,或在脚本中排除不需要检查的目录。

6.1 通过命令行参数调整行为

通过选择不同的命令行参数来控制检查的严格程度:

# 只做格式合法性检查(well-formedness),不进行 DTD 验证
xmllint --noout document.xml

# 使用 --nowarning 抑制解析器警告
xmllint --noout --nowarning document.xml

# 使用 --pedantic 启用额外警告(更严格)
xmllint --noout --pedantic document.xml

# 尝试恢复后继续解析(适合排查问题,不建议作为严格 CI 门禁)
xmllint --recover --noout document.xml

# 不加载外部网络资源(适合离线环境)
xmllint --noout --nonet document.xml

# 不加载外部 DTD
xmllint --noout --nodefdtd document.xml

完整参数列表参见:xmllint 手册页 - PARSER OPTIONS

6.2 通过 pre-commit 框架屏蔽

通过 pre-commit 的 filesexcludetypes 参数控制 hook 作用的文件范围:

repos:
  - repo: local
    hooks:
      - id: xmllint-validate
        name: xmllint XML 验证
        entry: xmllint --noout
        language: system
        types: [xml]
        # 仅检查特定目录下的 XML 文件
        files: ^(config|data)/.*\.xml$
        # 排除自动生成或第三方目录
        exclude: ^(vendor/|generated/|node_modules/)

pre-commit 配置说明:pre-commit 配置 - hooks

6.3 通过 CI 脚本排除目录

在 CI/CD 流水线中通过 find 命令的 -not -path 参数排除不需要检查的目录:

find . -name '*.xml' \
  -not -path './vendor/*' \
  -not -path './generated/*' \
  -not -path './node_modules/*' \
  -not -path './.git/*' \
  -print0 | xargs -0 xmllint --noout

6.4 各方式对比

屏蔽方式 适用场景 粒度 持久性 官方文档
命令行参数 调整验证模式或严格程度 单次执行 仅当次运行 xmllint 手册页
pre-commit 配置 控制 hook 作用的文件范围和匹配模式 文件匹配模式 随项目配置 pre-commit 配置
CI 脚本排除 CI 流水线中排除特定目录 目录级别 随 CI 配置 --

← 返回目录 | ← 返回总览