XML文件换行符处理 Windows与Linux下XML换行差异

4次阅读

xml解析中换行符处理需分层统一:解析时遵循unicode标准化(cr/lf→lf),dom/sax序列化可能转义;elementtree默认压缩空白,应改用lxml或手动拼接text/tail;xsd校验失败需预处理换行或显式声明whitespace=”preserve”。

XML文件换行符处理 Windows与Linux下XML换行差异

XML解析时换行变成 ,怎么统一处理?

windows用rn(CR+LF),linux/macosn(LF),XML规范允许两者,但实际解析时,DOM/SAX常把rn转成字符引用 ,而n可能保留为 。这不是解析错误,是标准行为——XML处理器按Unicode规范规范化行结束符后,再序列化为字符引用。

  • 解析前不手动替换原始文本里的换行,否则可能破坏CDATA或属性值中的合法rn
  • 若需显示/比对一致,应在序列化后文本内容提取后统一 normalize:用str.replace(/rn/g, 'n').replace(/r/g, 'n')js)或text.replace('rn', 'n').replace('r', 'n')(Python)
  • Java的Document.normalizeDocument()不会改换行;真正起作用的是transformer输出时的setOutputProperty(OutputKeys.INDENT, "yes")配合自定义LineSeparator

xml.etree.ElementTree读取XML后,文本里n消失或错乱?

Python的ElementTree默认对文本内容做“空白压缩”:开头结尾的空白(含换行)被strip,中间连续空白(含n)被合并为单个空格。这不是bug,是它对“mixed content”的默认处理策略。

  • parser = XMLParser(strip_cdata=False)不能解决换行问题;真正要关的是remove_blank_text——但ElementTree原生不支持,得换lxml.etree并设parser = etree.XMLParser(remove_blank_text=False)
  • 更轻量的做法:提取文本后,用elem.text or '' + elem.tail or ''拼接,再手动保留换行逻辑
  • 注意:etree.toString(elem, encoding='unicode', method='xml')输出时换行由pretty_print控制,和源文件换行无关

Java中javax.xml.parsers.DocumentBuilder解析后getTextContent()返回的换行不可靠?

DocumentBuilder遵循W3C DOM Level 3 Core规范:所有文本节点中的换行符在解析时被标准化为n,但后续调用getTextContent()会把所有子文本节点连起来,中间无分隔——如果XML里有元素穿插在段落中,换行就彻底丢失。

  • 不要用getTextContent()提取带格式的多行文本;改用遍历childNodes,对每个Node.TEXT_NODE单独取getNodeValue()
  • 如果必须用getTextContent(),且源XML已用xml:space="preserve"标记了该元素,则JDK 8+的DocumentBuilder会尊重它(需确保setFeature("<a href="https://www.php.cn/link/6c5184483cf53cdccb474420b29a911c">https://www.php.cn/link/6c5184483cf53cdccb474420b29a911c</a>", false)未关闭)
  • Transformer输出时加outputProps.setProperty(OutputKeys.INDENT, "yes")只影响缩进,不影响文本节点内的换行存留

XML Schema(XSD)里xs:string字段校验失败,报错含Invalid white space character

这是XSD处理器(如Xerces)在strict模式下拒绝rtn等非Char类Unicode字符。XML 1.0规范定义的Char确实包含tnr,但XSD 1.0的xs:string默认使用whiteSpace="preserve",而某些老版本处理器(尤其.NET Framework 2.0–4.0)实现有偏差。

  • 检查实际报错字符:用hexdump -C file.xml | grep -A1 -B1 '0d|0a'确认是否混入了r(0x0d)而XSD要求纯LF
  • 在XSD中显式声明<whitespace value="preserve"></whitespace>,避免依赖默认值
  • 更稳妥的方式:预处理XML,用sed ':a;N;$!ba;s/rn/n/g' file.xml > clean.xml(Linux)或powershell -Command "(Get-Content file.xml) -replace "rn", "n" | Set-Content clean.xml"windows

换行符本身不是数据问题,是不同环节对“文本边界”的解释权分散导致的——解析器、序列化器、XSD引擎、甚至终端显示都可能各自normalize一次。真要稳,就得在IO边界做一次确定性清洗,而不是依赖某一层的“应该保持原样”。

text=ZqhQzanResources