The following code can work for XML default namespace.
<?php
$xml = <<<EOT
<?xml version="1.0" encoding="UTF-8"?>
<entry xmlns="http://www.w3.org/2005/Atom" xmlns:other="http://other.w3.org/other" >
<id>uYG7-sPwjFg</id>
<published>2009-05-17T18:29:31.000Z</published>
</entry>
EOT;
$doc = new DOMDocument;
$doc->loadXML($xml);
$xpath = DOMXPath($doc);
$xpath->registerNamespace('atom', "http://www.w3.org/2005/Atom");
$xpath_str = '//atom:entry/atom:published/text()';
$entries = $xpath->evaluate($xpath_str);
print $entries->item(0)->nodeValue ."\n";
?>
説明
bool DOMXPath::registerNamespace
( string $prefix
, string $namespaceURI
)
DOMXPath オブジェクトに、 namespaceURI および prefix を登録します。
パラメータ
- prefix
-
プレフィックス。
- namespaceURI
-
名前空間の URI。
返り値
成功した場合に TRUE を、失敗した場合に FALSE を返します。
DOMXPath::registerNamespace
dulao5 at gmail dot com
16-Jun-2009 04:01
16-Jun-2009 04:01
agent009
31-Mar-2009 09:55
31-Mar-2009 09:55
Ok, here's a function that extends XPath syntax with the following special characters:
~ inserts default namespace prefix if defined
# shorthand for text()
% shorthand for comment()
$ shorthand for node()
?* shorthand for processing-instruction()
?foo shorthand for processing-instruction("foo")
? shorthand for processing-instruction("")
^ escapes following character (with literal or SGML entity as needed)
All of the above except ^ are ignored within quoted strings
<?php
function extendXPath($str, $defns = NULL) {
$quote = false;
$map = array(
'~' => isset($defns) ? "$defns:" : '',
'#' => 'text()',
'%' => 'comment()',
'$' => 'node()'
);
$out = '';
for ($i = 0, $len = strlen($str); $i < $len; $i++) {
$c = $str[$i];
if (!$quote && array_key_exists($c, $map)) {
$out .= $map[$c];
} else switch ($c) {
case '^':
$out .= htmlspecialchars($str[++$i], ENT_QUOTES);
break;
case '?':
if ($quote) {
$out .= $c;
} elseif ($str[$i + 1] == '*') {
$out .= 'processing-instruction()';
$i++;
} else {
preg_match('/^\w+/', substr($str, $i + 1), $matches);
$out .= 'processing-instruction("'.$matches[0].'")';
$i += strlen($matches[0]);
};
break;
case '"':
$quote = !$quote;
default:
$out .= $c;
};
};
return $out;
}
?>
adam dot prall at thinkingman dot com
09-Jun-2008 06:49
09-Jun-2008 06:49
Just a quick "gotcha" that may sound stupid:
If you've registered your namespaces, loaded your XHTML, etc., into your XPath's DOMDocument object and <i>still</i> can't get it to work, check to make sure you haven't used the DOMDocument's loadHTML() or loadHTMLFile() function. For XHTML <i>always use the XML versions</i>, otherwise your XPath will never, ever work. Save yourself a couple hours of frustration...
cameron kellough
15-Apr-2007 02:33
15-Apr-2007 02:33
This is called prefix mapping and it is necessary to use xpath to handle documents which have default namespaces. //root/item will search for items with no namespace, not items with the namespace described as the default in the xmlns declaration. This problem is maddening as it just looks on the surface like xpath isn't working.
spam at spam dot spam
01-Apr-2005 05:46
01-Apr-2005 05:46
It is mentioned in a few places on the web, but it wasn't mentioned here. You need to use this function to set up a prefix for the default namespace of a document.
For instance, if you are trying to parse a Microsoft Spreadsheet XML file, which has the default namespace of "urn:schemas-microsoft-com:office:spreadsheet":
$doc = DOMDocument::load("my_spreadsheet.xml);
$xpath = new DOMXPath($doc);
$xpath->registerNamespace("m",
"urn:schemas-microsoft-com:office:spreadsheet");
$query = '/m:Workbook/m:Worksheet[1]/m:Table';
$result = $xpath->query($query, $doc);
You can use anything in place of the 'm', but you have to specify something! Just asking for "/Workbook/Worksheet/Table" doesn't work.
