Почему этот запрос XPath не выполняется?Я сделал ошибку с DOMXPath? - PullRequest
0 голосов
/ 13 января 2011

Этот вопрос немного сложен, так как есть много движущихся частей, но я постараюсь минимизировать и использовать только самые подходящие фрагменты.

Я работаю над анализатором документов XML / XHTML, основанным на классах DOM в PHP, но похоже, что часть, использующая DOMXPath, не работает. Учитывая этот пример документа:

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:zuq="http://localhost/~/zuqml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
</head>
<body>
    <h1 id="pageHeading">
        <zuq:data name="pageHeading" />
    </h1>
    <p id="pageDescription">
        <zuq:data name="pageDescription">
            <zuq:format type="trim">
                <zuq:param name="length">300</zuq:param>
                <zuq:param name="append">...</zuq:param>
            </zuq:format>
        </zuq:data>
    </p>
    <div id="toolbar">
        <zuq:region name="toolbar" />
    </div>
    <div id="postWrap">
        <zuq:region name="post">
            <div class="post">
                <img height="200" width="200">
                    <zuq:attr name="src">
                        ./src/<zuq:data name="postImageSrc" />
                    </zuq:attr>
                </img>
                <h2><zuq:data name="postHeading" /></h2>
                <p>
                    <zuq:data name="postBody">
                        <zuq:format type="trim">
                            <zuq:param name="length">300</zuq:param>
                            <zuq:param name="append">
                                <a>
                                    <zuq:attr name="href">
                                        ./?postId=<zuq:data name="postId" />
                                    </zuq:attr>
                                    More »
                                </a>
                            </zuq:param>
                        </zuq:format>
                    </zuq:data>
                </p>
            </div>
        </zuq:region>
    </div>
</body>
</html>

Я создал анализатор, который принимает объект DataObject (который по сути является просто причудливым деревом других DataObject объектов) и выполняет циклический анализ документов с использованием данных в дереве. Исходные пути документа также хранятся в дереве.

Конструктор синтаксического анализатора:

public function __construct(DataObject $dataObject){
    $this->_dataObject = $dataObject;
}

Открытый render метод, вызываемый для возврата документа в виде строки:

public function render($filename = null){
    $document = new DOMDocument;
    $frag = $this->_build($document, $this->_dataObject);
    if(is_null($filename)){
        return $document->saveXML($frag);
    }else{
        //render to file
    }
}

И, наконец, приватный _build метод, в котором происходит суть действия:

protected function _build(DOMNode $node, DataObject $dataObject){
    $ownerDocument = $node instanceof DOMDocument
        ? $node
        : $node->ownerDocument;

    $buffer = $ownerDocument->createDocumentFragment();    

    for($dataIndex = 0; $dataIndex < $dataObject->count(); $dataIndex++){

        $frag = $ownerDocument->createDocumentFragment();
        if(!$dataObject->hasParent() || ($dataObject->getFilename() != $dataObject->getParent()->getFilename())){
            $frag->appendXML(file_get_contents($dataObject->getFilename()));
        }else{
            foreach($node->childNodes as $child){
                $frag->appendChild($child->cloneNode(true));
            }
        }
        $frag->normalize();

        $xpath = new DOMXPath($ownerDocument);
        $xpath->registerNamespace('zuq', $ownerDocument->lookupNamespaceURI('zuq'));

        //THIS IS WHERE THE TROUBLES ARE
        $nodeList = $xpath->query('.//zuq:data[not(ancestor::zuq:region)]', $frag);

        for($nodeIndex = $nodeList->length - 1; $nodeIndex >= 0; $nodeIndex--){

            //PERFORM REPLACEMENTS

        }
        $buffer->appendChild($frag);
    }
    return $buffer;
}

Я понимаю, что это довольно много, но если есть проблема, она должна быть где-то там. Проблема в том, что запрос XPath не возвращает никаких узлов . Я проверил это прямо на документах, и он отлично работает. Он находит все элементы <zuq:data />, которые находятся за пределами любых элементов <zuq:region />, в контексте данного узла (которые в рекурсии являются регионами, но я еще не там), что позволит анализировать каждый уровень региона по отдельности.

Когда я использую $nodeList = $xpath->query('.//*', $frag); и перебираю получившийся $nodeList, он содержит все элементы документа, от <html> до самых вложенных.

Почему мой $nodeList = $xpath->query('.//zuq:data[not(ancestor::zuq:region)]', $frag); запрос не выполняется? Я действительно надеюсь, что все просто: «О, вы просто забыли _ _.»

Заранее, я очень признателен за любую помощь, и, если потребуется более подробная информация, я был бы рад предоставить, просто дайте мне знать.

1 Ответ

2 голосов
/ 13 января 2011

запрос не выполняется?Я действительно надеюсь, что все просто: «О, ты просто забыл __.»

Я думаю, что это так.Используйте статический URI 'http://localhost/~/zuqml' лучше, чем $ownerDocument->lookupNamespaceURI('zuq')

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...