xmlparse() 必须指定 DOCUMENT 或 CONTENT 模式:DOCUMENT 要求完整 XML(单根节点),CONTENT 允许片段;xpath() 需 xml 类型输入并正确处理命名空间;xmlserialize() 注意编码兼容性与空白控制;高频查询应避免在 WHERE 中直接用 xpath(),改用生成列或表达式索引。

xmlparse() 解析字符串为 XML 值时,必须指定 DOCUMENT 或 CONTENT
PostgreSQL 不允许直接把字符串当 XML 用,xmlparse() 是唯一入口,且强制要求声明解析模式。漏写 DOCUMENT 或 CONTENT 会报错:ERROR: xmlparse requires a document or content keyword。
区别在于:DOCUMENT 要求输入是完整、有且仅有一个根节点的 XML(如 ),而 CONTENT 允许片段(如 )。
- 存整份配置文件?用
xmlparse(DOCUMENT ' ')- x
- 只提取一段标签内容?用
xmlparse(CONTENT '- x
- y
') - 若误用
DOCUMENT解析片段,会报:ERROR: invalid XML document: invalid root element
xpath() 提取节点前,确保输入是 xml 类型且命名空间处理得当
xpath() 不接受 text 或 varchar,传入非 xml 值会直接报错:ERROR: function xpath(unknown, xml) does not exist。常见错误是忘了套一层 xmlparse()。
更隐蔽的问题是命名空间。如果 XML 带 xmlns,XPath 表达式里不声明前缀,结果永远为空。
SELECT xpath('/root/item/text()',
xmlparse(DOCUMENT '- abc
'));
上面返回空数组。正确做法是用 ARRAY[ARRAY['x', 'http://example.com']] 注册命名空间:
SELECT xpath('/x:root/x:item/text()',
xmlparse(DOCUMENT '- abc
'),
ARRAY[ARRAY['x', 'http://example.com']]);
xmlserialize() 输出时注意 encoding 和 whitespace 控制
xmlserialize() 把 xml 值转成字符串,默认编码是 UTF-8,但如果你显式指定 DOCUMENT ENCODING 'ISO-8859-1',而内容含中文,就会报错:ERROR: character with byte sequence 0xe4 0xb8 0xad in encoding "UTF8" has no equivalent in encoding "ISO_8859_1"。
蛋糕连锁店网站管理系统(含小程序)是海南赞赞网络公司针对甜品糕点连锁企业开发的建站系统。程序主要采用了 thinkphp5内核开发,拥有独立自主的标签系统、函数系统、极方便二次开发,网站设计人员可以在该系统基础上设计出漂亮的网站模板。该系统现已在部分地区糕点连锁公司使用。
另外,它默认保留原始换行与缩进;若用于生成 API 响应或比对哈希,建议加 INDENT 或手动 REPLACE() 清理空白:
- 要压缩输出:先
xmlserialize(CONTENT x AS text),再用regexp_replace(... , E'\\s+', ' ', 'g') - 要带缩进的可读格式:加
INDENT子句,如xmlserialize(CONTENT x AS text INDENT) - 别在
xmlserialize()中混用DOCUMENT和CONTENT模式去匹配原始解析方式,否则可能多出/少掉根节点
性能敏感场景下,避免在 WHERE 或 JOIN 条件中反复调用 xpath()
xpath() 是纯函数,无法走索引,每次调用都要全量解析 XML 文本并执行 XPath 引擎。如果表里有上万行 XML 字段,又在 WHERE xpath(...) = 'value' 中使用,查询会极慢。
可行解法只有两个:
- 提前把关键字段抽出来,用生成列(PostgreSQL 12+)固化:
ALTER TABLE docs ADD COLUMN title text GENERATED ALWAYS AS (xpath('//title/text()', content)::text[]) [1] STORED - 或建表达式索引:
CREATE INDEX idx_docs_title ON docs USING btree ((xpath('//title/text()', content)::text[])[1])) - 注意:
xpath()返回的是xml[]数组,取值必须用下标(如[1])并显式类型转换,否则索引无效
XML 字段本身不是为高频查询设计的,真要按内容检索,优先考虑 JSONB + GIN 索引,除非你明确需要 XML Schema 验证或 XSLT 处理能力。









