什么是DomDocument命名空间?

时间:2012-11-04 00:21:39

标签: php xml rss domdocument xml-namespaces

$xpath->registerNamespace('slash', 'http://purl.org/rss/1.0/modules/slash/');

据我所知,它们就像文档定义一样,需要识别某些XML元素。

PHP实际上是否对该URL发出请求并验证该元素是否存在于文档定义中?

因为该网址显示404 not found页面:(

$result = $xpath->evaluate('string(//atom:entry[3]/slash:comments)');

这可能是我在尝试从RSS提要中检索<slash>元素的值时获取空字符串的原因吗?

4 个答案:

答案 0 :(得分:5)

$xpath->registerNamespace('slash', 'http://purl.org/rss/1.0/modules/slash/');
     

据我所知,它们就像文档定义一样,需要识别某些XML元素。

     

PHP实际上是否对该URL发出请求并验证该元素是否存在于文档定义中?


URI标识XML namespace,表示XML词汇表。这些名称空间旨在使用具有不同含义的相同术语来处理不同的上下文。对于名称空间,单个XML文件可以包含具有相同“名称”的标记和属性,这些标记和属性通过前缀限定。例如,您可以拥有这样的xml文档:

<html xmlns="http://www.w3.org/1999/xhtml" 
        xmlns:human="http://sample.xml.com/Human">
  <title>John Smith measures.</title>
  <body>
    <human:name>John</human:name> <human:surname>Smith</human:surname>
    is <human:height unit="feet">6</human:height> feet tall.
  </body>
</html>

在此类内容中,“human”前缀用于标记 http://sample.xml.com/Human 命名空间中的元素,空字符串(即默认前缀)用于标记< strong> http://www.w3.org/1999/xhtml 命名空间。这些URI是名称空间标识符,而不是模式位置(可以用DOCTYPE declarationXML Schema instance表示)。在命名空间URI标识的位置提供命名空间的正确文档是一个很好的做法,但它不是必需的(实际上xhtml命名空间URI指向相关的W3C文档,但是您正在寻找的RSS扩展,不是)

但请注意,resolveExternalsvalidateOnParse都会影响目标xml引用的DTD或模式定义的下载,但不是命名空间文档。绝不是,任何解析器都会下载这样的文档,因为它是供人类使用的。

$result = $xpath->evaluate('string(//atom:entry[3]/slash:comments)');
     

这可能是我在尝试从RSS提要中检索元素值时获取空字符串的原因吗?


首先,检查源xml是否包含正确的xmlns声明,并且它在第三个 atom条目中包含一个<slash:comments>节点(注意,第三个,因为 xpath索引是一个基于,因此//atom:entry[1]表示每个条目在其父节点中是第一个,//atom:entry[2]表示第二个,依此类推。) 如果是这样,我怀疑您忘记注册 atom 命名空间 尝试这样的事情(根据用户对DOMXPath::registerNamespace文档的贡献改编):

$doc = new DOMDocument;
$doc->loadXML($xml); // your xml string here
$xpath = new DOMXPath($doc);

$xpath->registerNamespace('atom', "http://www.w3.org/2005/Atom");
$xpath->registerNamespace('slash', 'http://purl.org/rss/1.0/modules/slash/');

$result =  $xpath->evaluate('string(//atom:entry[3]/slash:comments)');

您可以在http://codepad.org/JX8RpaKu

看到这种情况

实际上,要使用合格的xpath,您还需要注册默认命名空间。

答案 1 :(得分:2)

你有多个问题。我将尝试逐一解决这些问题:

$xpath->registerNamespace('slash', 'http://purl.org/rss/1.0/modules/slash/');
     

据我所知,它们就像文档定义一样,需要识别某些XML元素。

是的,每当你有一个带有命名空间的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。差别在于 Identifier Locator

The URI Pill: Can be URL or URN

要使XML命名空间正常工作,不需要找到任何内容。只需要识别名称空间。因此,可以使用任何URI表示有效的XML命名空间。例如,fantasy:space是一个有效的URI,并且完全限定了要求以指定XML命名空间。但是当你在浏览器中输入它时,你甚至不会得到任何服务器响应(你的浏览器不知道&#34;幻想&#34;代表什么)。

所以你得到的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中的

Getting a string of a nodeset表示:

  

通过返回文档顺序中第一个节点集中的string-value of the node,将节点集转换为字符串。如果节点集为空,则返回空字符串。

由于节点是元素,因此字符串值the element node表示:

  

元素节点的字符串值是文档顺序中元素节点的所有文本节点后代的字符串值的串联。

所以这里有两个解释为什么你得到一个空字符串:node-set为空或者elements-value只是一个空字符串。

您可以使用count() function快速了解节点集内的节点数:

$result = $xpath->evaluate('count(//atom:entry[3]/slash:comments)');

然后应该让您更好地了解这两种情况中的哪一种情况。由于你没有共享源XML,所以不能说为什么然而它 - 正如我所假设的 - 不包含任何节点。看到来源应该很容易澄清这一点。

在此之前,我只能猜测您可能正在解析不包含<atom:entry>元素而只包含<item>元素的RSS 2 Feed。看我的例子:

$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

输出值&#34; 1&#34;作为第三项的评论计数。这是标准Wordpress博客的源代码。 I have put this online as an interactive example, so you can see it in action and enter your feed URL

顺便说一句:如果您在之后创建了DOMXPath对象,那么您已经加载了XML,只要您知道就不需要注册名称空间URI。在文档中使用哪些前缀。这就是为什么在示例中我没有注册任何namespace-URI。

答案 2 :(得分:1)

如果您想检索命名空间节点的内容,您是否尝试过getElementsByTagNameNS

$dom - new DOMDocument($url);
$slashEls = $dom->getElementsbyTagNameNS('slash', 'slash'); // Assuming the element is <slash:slash> in the XML
foreach($slashEls as $slash) {
    // ...
}

答案 3 :(得分:1)

有关命名空间的教程,13岁但仍然有用,请参阅

http://www.jclark.com/xml/xmlns.htm