命名空间前缀未定义。如何定义它 automatically/ignore 错误?

Namespace prefix isn't defined. How can I define it automatically/ignore error?

我制作了一个 PHP 脚本来解析 XML 文件,当我尝试解析它时,出现错误:

2: DOMDocument::load(): Namespace prefix edf for represent on info is not defined in /users/zzz/testing/meta.xml, line: 2

我一直在寻找修复程序,但找不到任何修复程序,所以我在此处发布。如您所见,我正在使用 DOMDocument class.

我的解析代码 XML 看起来像:

$dom = new DOMDocument();
$metaXML = $dom->load($path."/meta.xml");

路径和一切都是正确的,我确定。当我删除前缀时,它工作正常。 XML 看起来像:

<meta>
    <info gamemodes="race" type="map" edf:represent="false"></info>
</meta>

edf:represent="false" 导致错误。 我不想手动删除 edf 命名空间前缀,因为这不是我要解析的唯一 XML 文件。有几百个,而且还在增加。

所以,我的问题是,如何忽略此错误(仅针对 XML 命名空间的东西)或者如何通过 DOMDocument class define/remove 命名空间前缀?

XML 文件本身不是 namespace-well-formed,因为它使用了未声明的命名空间前缀。删除未声明的名称空间前缀,或声明它,例如:

<meta xmlns:edf="http://www.example.com/">
    <info gamemodes="race" type="map" edf:represent="false"></info>
</meta>

更新: 您不能使用 XML 库执行此操作,因为 XML 格式不正确。您必须手动执行或以编程方式将文件作为文本操作,而不是 XML。一旦您的文本格式正确 XML,您就可以使用标准 XML 库来处理它。

这是 @Daniel 提出的基于文本的程序化编辑建议:


如果您需要在多个文件中更正此问题,请考虑使用 'sed' 等工具将您的元标记替换为更正后的版本。例如,要将文件夹中 <meta 的所有实例替换为 <meta xmlns:edf="http://www.example.com/"。你可以使用这个命令

sed -i -- 's/<meta/<meta\ xmlns\:edf\=\"http\:\/\/www.example.com\/\"/g' *

有关如何使用 sed 的更多信息,请参阅 https://unix.stackexchange.com/questions/112023/how-can-i-replace-a-string-in-a-files


格式良好的 XML 应始终使用 XML 解析器进行解析,但有时像上面这样的快速修复可以帮助我们实现目标。

另请参阅:

  • 此 Q/A 涵盖在 XML 组件名称中是否允许在使用 XML 名称空间前缀之外使用冒号。
  • Is there any difference between 'valid xml' and 'well formed xml'? This answer 解释了 namespace-well-formed 在 XML.[=42= 中的概念]

这是警告,不是错误。所以 XML 仍然可以使用,但是它坏了。最好的解决方案是修复 XML - 定义命名空间。

定义命名空间不会自动工作。名称空间前缀只是一个别名,实际的名称空间是 xmlns 属性的值。别名仅对元素及其后代有效。必须修复生成 XML 的 script/application,以便它添加命名空间定义。

<meta xmlns:edf="urn:example">
    <info gamemodes="race" type="map" edf:represent="false"></info>
</meta>

解析器将解析命名空间。您可以将 "edf:represent" 读作“{urn:example}represent”。

但是您可以使用 libxml_use_internal_errors() 阻止解析错误和警告。

$xml = <<<'XML'
<meta>
    <info gamemodes="race" type="map" edf:represent="false"></info>
</meta>
XML;

libxml_use_internal_errors(TRUE);

$dom = new DOMDocument();
$dom->loadXml($xml);

echo $dom->saveXml();

输出:

<?xml version="1.0"?>
<meta>
    <info gamemodes="race" type="map" represent="false"/>
</meta>

使用 libxml_get_errors() 您可以实现自己的错误处理。

如您在输出中所见,XML 解析器删除了名称空间前缀。这意味着 "represent" 现在是一个没有命名空间的属性,它改变了它的身份。请务必小心,represent{urn:example}represent 是两个不同的名称,您丢失了相关的上下文信息。