PHP: retrieve all declared namespaces of a DOMElem

2019-02-21 21:53发布

I am using the DOM extension to parse an xml file containing xml namespaces. I would have thought that namespace declarations are treated just like any other attribute, but my tests seem to disagree. I have a document that starts like this:

<rdf:RDF
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns="http://purl.org/rss/1.0/"
    xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/"
    xmlns:dc="http://purl.org/dc/elements/1.1/"
    xmlns:syn="http://purl.org/rss/1.0/modules/syndication/"
    xmlns:prism="http://purl.org/rss/1.0/modules/prism/"
    xmlns:admin="http://webns.net/mvcb/"
    >

And a test code like this:

$doc = new DOMDocument();
$doc->loadXml(file_get_contents('/home/soulmerge/tmp/rss1.0/recent.xml'));
$root = $doc->documentElement;
var_dump($root->tagName);
# prints 'string(7) "rdf:RDF"'
var_dump($root->attributes->item(0));
# prints 'NULL'
var_dump($root->getAttributeNode('xmlns'));
# prints 'object(DOMNameSpaceNode)#3 (0) {}'

So the questions are:

  1. Does anyone know where could I find the documentation of DOMNameSpaceNode? A search on php.net does not yield any useful result.
  2. How do I extract all those namespace declarations from that DOMElement?

2条回答
Juvenile、少年°
2楼-- · 2019-02-21 22:15

Note, that

echo $root->getAttributeNode('xmlns')->nodeValue . "\n";
echo $root->getAttribute('xmlns') . "\n";
echo $root->getAttribute('xmlns:syn') . "\n";

all work as expected, and print out

http://purl.org/rss/1.0/
http://purl.org/rss/1.0/
http://purl.org/rss/1.0/modules/syndication/

because DOMNameSpaceNode is a Node, not a NodeCollection.

Just clarifying, that, unless something in PHP DOM extension changes, XPath (as explained by VolkerK) is the only native way to get all the namespaces, regardless of documentation.

查看更多
甜甜的少女心
3楼-- · 2019-02-21 22:20

Unless there is a more direct way you can use XPath and its namespace axis.
e.g.

<?php
$doc = new DOMDocument;
$doc->loadxml('<rdf:RDF
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns="http://purl.org/rss/1.0/"
    xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/"
    xmlns:dc="http://purl.org/dc/elements/1.1/"
    xmlns:syn="http://purl.org/rss/1.0/modules/syndication/"
    xmlns:prism="http://purl.org/rss/1.0/modules/prism/"
    xmlns:admin="http://webns.net/mvcb/"
    >
...
</rdf:RDF>');
$context = $doc->documentElement;

$xpath = new DOMXPath($doc);
foreach( $xpath->query('namespace::*', $context) as $node ) {
  echo $node->nodeValue, "\n";
}

prints

http://www.w3.org/XML/1998/namespace
http://webns.net/mvcb/
http://purl.org/rss/1.0/modules/prism/
http://purl.org/rss/1.0/modules/syndication/
http://purl.org/dc/elements/1.1/
http://purl.org/rss/1.0/modules/taxonomy/
http://purl.org/rss/1.0/
http://www.w3.org/1999/02/22-rdf-syntax-ns#

edit and btw: I haven't found documentation for DOMNameSpaceNode either. But you can "deduct" (parts of) its functionality from the source code in ext/dom/php_dom.c
It doesn't seem to expose any methods and exposes the properties

"nodeName", "nodeValue", "nodeType",
"prefix", "localName", "namespaceURI",
"ownerDocument", "parentNode"

all handled by the same functions as the corresponding DOMNode properties.

查看更多
登录 后发表回答