XQuery移除XML元素换行函数需求及长字符串赋值换行问题
解决XQuery生成XML时元素内容自动换行的问题
我懂你遇到的麻烦:用XQuery给
一、直接处理单个元素的换行问题
如果只需要处理特定的fn:replace()函数干掉所有换行符(不管是Windows的\r\n还是Unix的\n)就行。要是原始字符串还带换行前后的多余空格,也能一并清理:
let $raw-long-string := "86E95A47AD2037B203521BBE7DAC71A11FE2DBD539D21CF66A9024B30505090F52F687F5BB299BD21A25E2ED01079A009B25FCFB7DCCBAF1DAB16E78B8CE179A922B94957989DBF531F967E46ACFB1B474A6F4CFD6AFB8C61D5BBB62346C502F837A68A15CD12ED90C03371EFB8C9922FB6B7860" (: 模拟带换行的原始字符串,比如从文件/数据库读取的内容 :) let $string-with-newlines := replace($raw-long-string, "(.{50})", "$1 ") return <ABC> <X>{replace($string-with-newlines, '\s*\r?\n\s*', '')}</X> <Y>70406352</Y> </ABC>
这段代码里,replace($string-with-newlines, '\s*\r?\n\s*', '')会把换行符以及换行前后的空格全部替换为空,刚好匹配你期望的输出效果——
二、编写通用函数批量处理元素换行
要是需要处理多个元素,写个通用函数会更省心。这个函数能递归遍历XML元素的所有文本节点,统一移除换行符:
declare function local:remove-element-newlines($elem as element()) as element() { element { node-name($elem) } { for $child in $elem/node() return if ($child instance of text()) then replace($child, '\r?\n', '') else if ($child instance of element()) then local:remove-element-newlines($child) else $child } }; (: 函数使用示例 :) let $original-xml := <ABC> <X> 86E95A47AD2037B203521BBE7DAC71A11FE2DBD539D21CF66A9024B30505090F52F687F5BB299BD21A25E2ED01079A009B25FCFB7DCCBAF1DAB16E78B8CE179A922B94957989DBF531F967E46ACFB1B474A6F4CFD6AFB8C61D5BBB62346C502F837A68A15CD12ED90C03371EFB8C9922FB6B7860 </X> <Y>70406352</Y> </ABC> return local:remove-element-newlines($original-xml)
这个函数的逻辑很清晰:
- 遍历目标元素的所有子节点
- 遇到文本节点就替换掉所有换行符
- 遇到子元素就递归处理子元素的内容
- 注释、处理指令这类非文本节点保持原样
不管你的XML结构有多复杂,都能一次性清理所有元素文本里的换行,输出紧凑的连续内容。
额外小技巧:关闭XML自动格式化
有些XQuery处理器(比如Saxon)会自动给XML输出加换行和缩进,这可能是换行的根源。你可以通过设置输出参数关闭格式化,比如在Saxon里添加:
declare option saxon:output "indent=no";
这样整个XML输出都会是紧凑格式,元素内容不会被自动插入换行。
内容的提问来源于stack exchange,提问作者sushmitha sen
相关产品推荐
相关产品推荐

