PHP expat 解析器:如何区分“真实”[CDATA[...]] 部分和普通的 TEXT 节点?

PHP expat parser : How to distinguish "real" [CDATA[...]] section from normal TEXT node?

提问人:RichardLiu 提问时间:5/30/2023 更新时间:5/30/2023 访问量:37

问:

我正在尝试使用内置的XML expat解析器在PHP中处理大型XML文件(~1GB)。我通过调用 来设置处理程序,以便我可以提取 TEXT 数据。xml_set_character_data_handler()

问题是,处理程序将在“正常”TEXT 节点和“实际”CDATA 部分(例如)上调用,但只有 CDATA 部分内容(即:“”)将传递给处理程序。<![CDATA[hello world]]>hello world

所以我的问题:有没有办法知道传递给字符数据处理程序的数据是普通的TEXT节点,还是部分的内容?<![CDATA[...]]>

我需要知道这一点,因为 XML 数据需要遵循严格的格式规则并且不允许使用,并且我应该为这些格式错误的 XML 文件生成错误报告。<![CDATA[...]]>

PS:我已经尝试过了,但无法获得我的任务所需的 curren 节点的行号。我认为在处理大型XML文件时调用不是一个好主意。XMLReaderXMLReader::expand()->getLineNo()

php xml xml 解析

评论

0赞 Michael Kay 5/30/2023
尽管 XML 规范对此并非 100% 规定,但社区中有一个普遍的共识,即作为 XML 文档的接收者,无论是否使用了 CDATA,您都应该以完全相同的方式对待文本内容。它与要求 XML 作者编写字符引用 as 而不是 : 大多数 XML 解析器不允许您查看已使用的内容,因此无法强制执行该规则。#x0D;#xd;
0赞 RichardLiu 5/30/2023
@MichaelKay 好吧,许多(如果不是大多数)XML 解析器确实允许您查看已使用的内容。PHP 内置有一个 nodeType 常量值 !CDATA 部分。 可以添加回调通知你下一个节点是!CDATA中。并允许您选择是保留还是剥离标题。如果 PHP XML expat 解析器只是将附加了标头的值传递给我,我会非常高兴,但我不知道如何在传递给处理程序之前阻止它剥离标头。XMLReaderXMLReader::CDATAlibexpatlibxml2<![CDATA[<![CDATA[
0赞 Michael Kay 5/31/2023
是的,有许多解析器可以让你做到这一点。这并不意味着这样做是个好主意。
0赞 RichardLiu 5/31/2023
@MichaelKay对于普通的XML解析器来说,它可能不是必需的,因为您所需要的只是提取值。但我需要的不是一个普通的XML解析器:我的任务是编写一个XML Linter工具来验证输入XML文件的语法和结构,并检查TEXT节点的值范围。!CDATA 部分未在我正在处理的 XML 文件的规则手册中指定,我应该将其记录为错误。
0赞 Michael Kay 6/2/2023
在我看来,CDATA 100% 等同于用 & 号转义特殊字符,在我看来,不允许这样做的“规则手册”是完全错误的。这样的规则书应该在结构级别(例如XSD或RelaxNG)而不是在词法级别上约束XML。

答: 暂无答案