命名空间前缀未定义。如何自动定义或忽略错误?

5
我做了一个PHP脚本来解析XML文件,但是当我尝试解析它时,出现了一个错误:
2:DOMDocument :: load():命名空间前缀edf代表的info未在/users/zzz/testing/meta.xml的第2行中定义。
我一直在寻找解决方法,但我找不到,所以我在这里发布。正如您所见,我正在使用DOMDocument类。
我的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类定义/删除命名空间前缀?

2个回答

3
XML文件本身不命名空间格式正确,因为它使用了未声明的命名空间前缀。要么删除未声明的命名空间前缀,要么声明它,例如:
<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' *

请参考https://unix.stackexchange.com/questions/112023/how-can-i-replace-a-string-in-a-files 了解如何使用sed。


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

另请参阅:


我该如何使用PHP自动定义或删除它?正如我所说,我有太多像这样的XML文件,我不想一个一个地更改。 - GTX
看到更新了。嗯,好的,我明白了。但是有没有办法检查XML是否“格式不正确”?因为现在它会返回一个错误并退出程序。我尝试使用if语句if(!metaXML) { ... },但它仍然返回一个错误。 - GTX
检查XML是否格式正确的方法很简单,只需解析它即可。如果它不是格式正确的,根据定义,您将会得到错误信息。 - kjhughes

3
这是一个警告而不是错误。因此,XML仍然可以使用,但是它已经损坏。最好的解决方案是修复XML文件,定义命名空间。
定义命名空间不会自动起作用。命名空间前缀只是实际命名空间的别名,其值为xmlns属性的值。该别名仅适用于该元素及其后代。生成XML文件的脚本/应用程序必须进行修复,以便添加命名空间定义。
<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是两个不同的名称,您会丢失相关上下文信息。


谢谢,我不知道libxml_use_internal_errors函数。现在它可以工作了。 - GTX

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接