PHP文档名称空间

PHP文档名称空间,php,dom,Php,Dom,我正在写一个脚本,它会获取一个网页,并检测像facebook一样的按钮被使用了多少次。因为这最好用DOM来完成,所以我决定使用PHP的DOMDocument 不过,我遇到的一个问题是facebook的like按钮: <fb:like send="true" width="450" show_faces="true"></fb:like> 由于该元素在技术上有一个名称空间“fb”,DOMDocument会抛出一条警告,指出未定义该名称空间前缀。然后,它继续去除前缀,所

我正在写一个脚本,它会获取一个网页,并检测像facebook一样的按钮被使用了多少次。因为这最好用DOM来完成,所以我决定使用PHP的DOMDocument

不过,我遇到的一个问题是facebook的like按钮:

<fb:like send="true" width="450" show_faces="true"></fb:like>

由于该元素在技术上有一个名称空间“fb”,DOMDocument会抛出一条警告,指出未定义该名称空间前缀。然后,它继续去除前缀,所以当我到达上述元素时,它的标签不再是fb:like,而是like


有没有办法“预注册”命名空间?有什么建议吗?

这就是你想要的吗

你可以试试。然后你可以运行类似于

$html = new simple_html_dom();
$html->load_file('fileToParse.html');
$count=0;
foreach($html->find('fb:like') as $element){
    $count+=1
}
echo $count;
这应该行得通

我进一步看了看,发现了这个。我从PHP.net上的

$dom = new DOMDocument;
$dom->loadHTML('fileToParse.html'); // or $dom->loadXML('fileToParse.html'); 
$likes = $dom->getElementsByTagName('fb:like');
$count=0;
foreach ($likes as $like) {
    $count+=1;
}
这一次之后,我被卡住了

$file=file_get_contents("other.html");
$search = '/<fb:like[^>]*>/';
$count  = preg_match_all($search , $file, $matches);
echo $count;
//Below is not needed
print_r($matches);
但是得到了与您相同的错误。

在使用xml解析器之前,您可以先对其进行修饰

$tidy = new tidy();
$config = array(
    'output-xml'   => true, 
    'input-xml'    => true, 
    'add-xml-decl' => true,
);
$tidy->ParseString($htmlSoup, $config);
$tidy->cleanRepair();
echo $tidy;

无法找到使用
DOM
的方法。我很惊讶正则表达式比
DOMDocument
慢,因为我通常不是这样<代码>STRPO应该是最快的,不过:

strpos($dom, '<fb:like');

strpos($dom),我也遇到了同样的问题,我提出了以下解决方案:

使用DOMDocument解析带有名称空间的HTML时,没有干净的方法可以不丢失名称空间,但有一些解决方法:

  • 使用另一个在HMTL代码中接受名称空间的解析器。在这里查看HTML解析器的详细列表。这可能是最有效的方法
  • 如果您想坚持使用DOMDocument,基本上必须对代码进行预处理和后处理

    • 在将代码发送到DOMDocument->loadHTML之前,请使用regex、loops或任何您想要查找所有名称空间标记并向包含名称空间的开始标记添加自定义属性的内容

      <fb:like send="true" width="450" show_faces="true"></fb:like>
      
      
      
      然后会导致

      <fb:like xmlNamespace="fb" send="true" width="450" show_faces="true"></fb:like>
      
      
      
    • 现在将编辑后的代码提供给DOMDocument->loadHTML。它将去掉名称空间,但保留导致

      <like xmlNamespace="fb" send="true" width="450" show_faces="true"></like>
      
      
      
    • 现在(再次使用正则表达式、循环或任何你想要的)找到所有带有属性xmlNamespace的标记,并用实际的名称空间替换该属性。别忘了也将名称空间添加到结束标记中
我不认为OP仍然在寻找答案,我只是为在他们的研究中发现这篇文章的任何人发布这篇文章。

由于这一问题从未“解决”,我决定继续为其他不喜欢研究正则表达式的人实现这一解决方案

// do this before you use loadHTML()    
// store any name spaced elements so we can re-add them later
$postContent = preg_replace('/<(\w+):(\w+)/', '<\1 data-namespace="\2"' , $postContent);

// once you are done using domdocument fix things up
// re-construct any name-spaced tags
$postContent = preg_replace('/<(\w+) data-namespace="(\w+)"/', '<\1:\2 ' , $postContent);
//在使用loadHTML()之前执行此操作
//存储任何名称分隔的元素,以便我们以后可以重新添加它们

$postContent=preg_replace('/尝试了正则表达式解决方案。。。 关闭标记有问题,因为它们不接受属性

<ns namespace="node">text</ns>
文本
(最重要的是,正则表达式没有寻找结束标记…) 最后我做了一些丑陋的事情,比如

$output = preg_replace('/<(\/?)(\w+):(\w+)/', '<\1\2thistaghasanamespace\3' , $output);

$output=preg_replace('/I以前使用过此选项,但为了提高速度,我想使用本机解决方案。不过,我可能必须默认返回此选项:(@Obto我在我的小网站上使用它,所以我在速度上没有问题。我已经更新了它,以获得另一个应该更快的解决方案。遗憾的是,这不起作用。在解析html时,fb名称空间前缀被去掉。因此,当搜索它时将什么也找不到,你必须搜索“like”相反。我想过这样做,但是页面根本不解析。嘿。DOMDocument的loadHTML显然内置了很多html信息。这听起来像是一个非常直接的解决方案,所以我决定使用它。这是我为讨厌正则表达式的人编写的代码。
//存储任何名称分隔的元素,以便我们以后可以重新添加它们de>
$postContent=preg_replace(“/这是一个很好的开始,但似乎会使标记在破折号后被截断。例如,gcse:searchbox结果只会变成gcse:searchbox
$output = preg_replace('/<(\/?)(\w+):(\w+)/', '<\1\2thistaghasanamespace\3' , $output);
$output = preg_replace('/<(\/?)(\w+)thistaghasanamespace(\w+)/', '<\1\2:\3' , $output);