现在的位置: 首页 > 问答 > 正文

Xpath strange behavior – not matching text nodes

2016年08月21日 问答 ⁄ 共 2768字 ⁄ 字号 暂无评论

While doing such things

foreach ($xpath->query('.//tpl-static', $domTemplateContainer) as $domStatic) {
    /* ... */
    $domStatic->parentNode->removeChild($domStatic);
}

All seems to work fine.

But when dealing with xml-comments and more importantly - text nodes it fails to work as intended:

foreach ($xpath->query('.//text()[normalize-space() = ""]', $domDocumentFragment) as $domNode) {
    $domNode->parentNode->removeChild($domNode);
}

some text nodes are just not selected but some are. I could not find logic behind this. Predicate does not matter.
But I also found following query works fine:./descendant-or-self::text()[normalize-space() = ""]

Why does .// only work for element nodes but not for text nodes? Is it libxml/php bug or something to be reported or I've missed something?

ADDITION:

Complete example (adapted from complex project):

$xml = '
<tpl-static>
    <link rel="shortcut icon" type="image/x-icon" href="/static/images/icon.ico" />
    <link rel="stylesheet" type="text/css" href="/static/css/html5reset-1.6.1.css" />
    <link rel="stylesheet" type="text/css" href="/static/css/style.css" />
    <script src="/static/js/underscore.js"></script>
    <!-- <script src="/static/js/jquery.adaptive-backgrounds.js"></script> -->
    <script src="/static/js/jquery.maskedinput.min.js"></script>
    <link href="/static/js/jquery-ui-1.11.2.custom/jquery-ui.css" rel="stylesheet"/>
    <script src="/static/js/jquery-ui-1.11.2.custom/jquery-ui.min.js"></script>
    <link rel="stylesheet" href="/static/js/jquery.magnific-popup/magnific-popup.css" />
    <script src="/static/js/jquery.magnific-popup/jquery.magnific-popup.js"></script>
    <script src="/static/templates/dealers-page-includes/page-includes.js"></script>
</tpl-static>
<br/>

';

$domDocument = new \DOMDocument('1.0', 'utf-8');
$xpath = new \DOMXPath($domDocument);
$domDocumentFragment = $domDocument->createDocumentFragment();
$domDocumentFragment->appendXml($xml);

$templateName = 'test';
//$it = $this;
$adoptTemplate = function($domTemplateContainer) use (&$adoptTemplate, /*$it,*/ $domDocument, $xpath, $templateName) {

    foreach ($xpath->query('.//comment()', $domTemplateContainer) as $domComment) {
        $domComment->parentNode->removeChild($domComment);
    }

    foreach ($xpath->query('.//tpl-static', $domTemplateContainer) as $domStatic) {
        foreach ($domStatic->childNodes as $curChildNode) {
            //$it->_domDocumentHead->appendChild($curChildNode->cloneNode(true));
        }
        $domStatic->parentNode->removeChild($domStatic);
    }
};

$adoptTemplate($domDocumentFragment);

// FAIL!
/*foreach ($xpath->query('.//text()[normalize-space() = ""]', $domDocumentFragment) as $domNode) {
    $domNode->parentNode->removeChild($domNode);
}*/
// HERE IS 
// workaround...
foreach ($xpath->query('./descendant-or-self::text()[normalize-space() = ""]', $domDocumentFragment) as $domNode) {
    $domNode->parentNode->removeChild($domNode);
}

if ($domDocumentFragment->childNodes->length > 1) {
    throw new \Exception('Single node expected in template "' . $templateName . '", ' . $domDocumentFragment->childNodes->length . ' given.');
}

给我留言

您必须 [ 登录 ] 才能发表留言!

×