你有多个问题。我会尝试逐一回答它们:
$xpath->registerNamespace('slash', 'http://purl.org/rss/1.0/modules/slash/');
From what I understand they act like document definitions, and are required to identify certain XML elements.
是的,每当您有一个带有命名空间的XML文档时,那么每个元素都可以在自己的命名空间中。
如果您想要访问它们自己的命名空间中的元素,则确实需要使用该命名空间来标识它们。例如,在XPath表达式中。
在PHP中,DOMDocument和其他基于libxml的XML扩展支持XML命名空间。
PHP实际上会请求该URL并验证该元素是否存在于文档定义中吗?
不,对于您提供的代码示例:
$xpath->registerNamespace('slash', 'http://purl.org/rss/1.0/modules/slash/');
PHP不会请求那个URL。你已经注意到这个URL是空的/返回404,所以你可能想要了解这一切是关于什么的。实际上,那个URL是一个URI。这就是标识符和定位器之间的区别。
![The URI Pill: Can be URL or URN](https://istack.dev59.com/3m8Tp.webp)
要使XML命名空间起作用,无需定位任何内容。只需要识别命名空间即可。因此,任何URI都可以表示有效的XML命名空间。例如,
fantasy:space
是一个有效的URI,并且完全符合指定XML命名空间的要求。但是,当您在浏览器中输入它时,您甚至不会收到任何服务器响应(您的浏览器不知道"fantasy"代表什么)。
因此,您获得的404错误不是导致您的XPath评估中斜杠为空的原因:
$result = $xpath->evaluate('string(//atom:entry[3]/slash:comments)');
你之所以在这里得到一个空字符串的原因是不同的。请看XPath表达式:
string(//atom:entry[3]/slash:comments)
这是要求节点集的字符串值。您已将节点集指定为:
//atom:entry[3]/slash:comments
在PHP DOMDocument中,“获取节点集的字符串”意味着:将节点集转换为字符串,方法是返回节点集中按文档顺序排列的第一个节点的
节点字符串值。如果节点集为空,则返回空字符串。
由于节点是元素,因此
元素节点的字符串值意味着:元素节点的字符串值是元素节点所有文本节点后代的字符串值按文档顺序连接起来的结果。
因此,这里有两种情况会导致你得到一个空字符串:要么节点集为空,要么元素的字符串值正好是一个空字符串。
您可以通过使用
count()
函数快速了解节点集合中节点的数量:
$result = $xpath->evaluate('count(//atom:entry[3]/slash:comments)');
这段文字的意思是:
“这样,你应该可以更好地了解到哪种情况是真实的。由于你没有分享源XML,不能确定具体的原因,但我猜测它可能不包含节点。查看源文件应该很容易澄清这个问题。”
“在此之前,我只能猜测你可能正在解析一个不包含元素而只有元素的RSS 2.0订阅。请参考我的示例:”
$feed = 'http://hakre.wordpress.com/feed/';
$doc = new DOMDocument();
$doc->load($feed);
$xpath = new DOMXPath($doc);
echo $xpath->evaluate('string(//item[3]/slash:comments)');
它输出了值“1”作为第三项的评论计数。这是标准WordPress博客的源。
我已将其在线发布为交互式示例,因此您可以看到它的运行情况并输入您的Feed URL。
顺便说一下:如果在加载XML之后创建
DOMXPath
对象,则只需知道文档中使用了哪些前缀,就不需要注册命名空间URI。这就是为什么在示例中我没有注册任何命名空间URI的原因。