Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/234.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 我的文件里有鬼魂吗?_Php_Domdocument - Fatal编程技术网

Php 我的文件里有鬼魂吗?

Php 我的文件里有鬼魂吗?,php,domdocument,Php,Domdocument,尝试简化正在运行的xpath,现在只显示空节点 来源:任何XML文件。假设 <?xml version="1.0" encoding="UTF-8"?> <html xmlns="http://www.w3.org/1999/xhtml" lang="pt-br" xml:lang="pt-br"> <head> <meta charset="utf-8"/><title>test</title> </head&g

尝试简化正在运行的xpath,现在只显示空节点

来源:任何XML文件。假设

<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" lang="pt-br" xml:lang="pt-br">
  <head> <meta charset="utf-8"/><title>test</title> </head>
  <body>
    <article id="etc"><p>Hello</p><p>Bye</p></article>
  </body>
</html>

工作原理是什么,为什么xpath没有运行?

这是因为您的xml定义了一个默认名称空间:

xmlns="http://www.w3.org/1999/xhtml"
因此,您需要注册一个名称空间,然后使用名称空间标记名进行搜索:

$xpath->registerNamespace('x', 'http://www.w3.org/1999/xhtml');
$entries = $xpath->query('//x:p');

这是W3C的DOMDocumentV1.0标准的一个老问题。关于XPath初学者的惊喜

关于(…)的一个常见问题是:
“为什么我觉得XPath表达式没有匹配的内容?”
这些问题的常见原因是没有正确定义XPath的命名空间

但是初学者是对的,这是一种丑陋的行为,是一种“默认的东西”。。。因此,让我们保留初学者关于什么是简单和好的直觉

看到一个XPath似乎不是您所需要的(XML在其标记没有前缀时的样子)是很可怕的。标记是简单的标记,需要简单的XPath

可靠的解决办法 用最佳解决方案修复丑陋的XPath查询行为。这一点很重要,因为root的
xmlns
属性,所以我们需要通过一个新的字符串XML来重新创建DOM对象:

$expTag = 'html';  // config expected tag-root
$expNs  = 'http://www.w3.org/1999/xhtml';  // config
// ...
$e = $dom->documentElement; // root node

// Validate input (as expecteds configs) and change tag root:
if ($e->nodeName==$expTag && $e->hasAttribute('xmlns') 
    && $e->getAttribute('xmlns')==$expNs) {
  // can't do $e->removeAttribute('xmlns') because is read-only!
  $xml = $dom->C14N(); // normalize quotes and remove repeateds
  $xml = preg_replace("#^<$expTag (.*?)xmlns=\"[^\"]+\"#", "<$expTag\$1", $xml);
  $dom = DOMDocument::LoadXML($xml);
} else 
     die("\n ERROR: something not expected.\n");
//...
$xpath = new DOMXPath($dom);
$entries = $xpath->query('//p'); // perfect, now back simple to express XPath!
$expTag='html';//配置所需的标记根
$expNs=http://www.w3.org/1999/xhtml';  // 配置
// ...
$e=$dom->documentElement;//根节点
//验证输入(按预期配置)并更改标记根:
如果($e->nodeName==$expTag&&$e->hasAttribute('xmlns'))
&&$e->getAttribute('xmlns')==$expNs){
//无法执行$e->removeAttribute('xmlns'),因为它是只读的!
$xml=$dom->C14N();//规范化引号并删除重复项
$xml=preg_replace(“#^query('//p');//完美,现在返回到简单的XPath表达式!
只有在没有限制的情况下才能使用此解决方案,如在上下文中

在其他实际环境中的问题是,将完整XML保存/重新加载为字符串的成本很高(CPU),为了安全起见,更昂贵的方法是将安全XML准备到正则表达式中


使用C14N(也适用于数字保存上下文中的其他内容)对于确保正则表达式的正确行为是必要的-严格来说,
getAttribute()
方法可能会受到属性重复的影响,但我们可以忽略这一“二阶”“效果,或将检查转移到正则表达式。

是的,您显示了点(!),现在我将在没有重影的情况下做梦……但让我们看看……很多网站和建议都说“默认XHTML名称空间
”(即使对于HTML5 as)…有些东西没有意义:命名空间
x
用于
x:y
标记,而不是用于更改默认行为。@PeterKrauss
x
registerNamespace
中是一个任意标识符。您可以在那里使用任何标识符,例如
peter
,因此它应该是
peter:p
:-)但是,是的,您必须明确指定名称空间:这就是为什么它首先存在的原因。是的,谢谢(!)…所以,这是(丑陋的)法则,我们接受…似乎这里的关键字也是“限定名”,当定义了
xmlns
属性时。无论
foreach($dom2->getElementsByTagName('p')作为$e)
(不需要registerNamespace),节点标记中不使用前缀(no
x:p
)。限定名只能在XPath查询中使用。
$expTag = 'html';  // config expected tag-root
$expNs  = 'http://www.w3.org/1999/xhtml';  // config
// ...
$e = $dom->documentElement; // root node

// Validate input (as expecteds configs) and change tag root:
if ($e->nodeName==$expTag && $e->hasAttribute('xmlns') 
    && $e->getAttribute('xmlns')==$expNs) {
  // can't do $e->removeAttribute('xmlns') because is read-only!
  $xml = $dom->C14N(); // normalize quotes and remove repeateds
  $xml = preg_replace("#^<$expTag (.*?)xmlns=\"[^\"]+\"#", "<$expTag\$1", $xml);
  $dom = DOMDocument::LoadXML($xml);
} else 
     die("\n ERROR: something not expected.\n");
//...
$xpath = new DOMXPath($dom);
$entries = $xpath->query('//p'); // perfect, now back simple to express XPath!