Почему я не могу выбрать нужный узел, используя это выражение PHP Xpath? - PullRequest
1 голос
/ 23 февраля 2010

Используя PHP, SimpleXML и функцию xpath (), я хочу выбрать дочерний узел, начиная с определенной точки.Не могли бы вы мне помочь?Я знаю, что в этом конкретном случае я мог бы использовать выражение, начинающееся с "//", но я хочу узнать, как правильно выбрать дочерний узел.Спасибо.

Первая попытка - ошибка с Неопределенное смещение: 0 ошибка

$navXmlObject = simplexml_load_file("main_navigation.xml");
$tmpObject = $navXmlObject->website->xpath('title[@lang="fr"]'); 
echo($tmpObject[0]["label"]);

Вторая попытка, добавление косой черты - также происходит сбой с той же ошибкой

$tmpObject = $navXmlObject->website->xpath('/title[@lang="fr"]'); 

XML-файл

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <website id="MainWeb">
        <title lang="fr" label="Mon site Web" />        
        <title lang="en" label="My web site" />     
        <menuNodes>

            <menuNode id="Home">
                <menuNodeData lang="fr" label="Accueil" url="/fr/accueil/" />
                <menuNodeData lang="en" label="Home" url="/en/home/" />
            </menuNode>

            <menuNode id="Prod">

                <menuNodeData lang="fr" label="Produits" url="/fr/produits/" />
                <menuNodeData lang="en" label="Products" url="/en/products/" />

                <menuNode id="Shoe">
                    <menuNodeData lang="fr" label="Chaussures" url="/fr/produits/chaussures/" />
                    <menuNodeData lang="en" label="Shoes" url="/en/products/shoes/" />
                </menuNode>

            </menuNode>

            <menuNode id="Biog">
                <menuNodeData lang="fr" label="Biographie du fondateur" url="/fr/biographie/" />
                <menuNodeData lang="en" label="Biography of founder" url="/en/biography/" />
            </menuNode>

        </menuNodes>
    </website>
</root>

Ответы [ 4 ]

1 голос
/ 23 февраля 2010

W3Schools имеет довольно хорошее учебное пособие по XPath , которое я рекомендую.

Как вы упомянули в своем вопросе, если вы хотите выделить все <title/> элементы в любом месте документа, вы можете использовать

//title

(к которому можно добавить предикат, например [@lang="fr"])

  • В XPath // означает «где угодно».
  • Если ваше выражение XPath начинается с //, это означает «где-нибудь в документе».
  • Если оно начинается с одного /, это означает "в корне документа."
  • Наконец, если он не начинается с косой черты, это означает «под узлом контекста».

Если вы знаете, что структура вашего дерева не изменится, точный путь к элементу <title/> будет

/root/website[@id="MainWeb"]/title[@lang="fr"]

Теперь предположим, что вы планируете реструктурировать дерево и, возможно, переместить узел <website/> под другим узлом. Вы можете сказать, «давайте посмотрим на узел <website/> в любом месте и найдем узел <title/>, который должен быть его дочерним элементом» , который в XPath будет

//website[@id="MainWeb"]/title[@lang="fr"]

Наконец, знайте, что вы можете использовать контекстный узел в качестве корня поиска, используя одну точку "." Например, используя SimpleXML, вы можете искать <title/> в любом месте в <website/>, используя

$navXmlObject->website->xpath('.//title')
1 голос
/ 24 февраля 2010

Настоятельно рекомендуется , чтобы вы обновились до последней стабильной сборки и наслаждались всеми усовершенствованиями, которые будут с ним. Теперь, когда все кончено, причина, по которой ваш код не работает, заключается именно в том, что такая старая версия SimpleXML не ведет себя так, как вы ожидаете.

Узел контекста для запросов находится не там, где вы ожидаете (по сравнению с saner, более поздние версии, например). Для простоты понимания, на мой взгляд, вам будет проще использовать абсолютный XPath.

Вот некоторые примеры, которые будут работать в вашем PHP 5.0.5 (и в текущих версиях):

$xmlObject->xpath("/root/website/title[@lang='fr']")
$xmlObject->xpath("./website/title[@lang='fr']")
$xmlObject->xpath("//website/title[@lang='fr']")
$xmlObject->xpath("website/title[@lang='fr']")

Чтобы добавить гаечный ключ в работу, вот пример, который просто глуп (но должен работать для вас в 5.0.5):

$xmlObject->website->menuNodes->xpath("title[@lang='fr']")
0 голосов
/ 25 февраля 2010

РЕШИТЬ!

Обновление до последней версии PHP решило проблему! Я полностью удалил PHP и Apache из своей системы и вместо этого использовал Uniform Server - портативную среду PHP / Apache (http://uniformserver.com/)

Спасибо всем за помощь.

0 голосов
/ 23 февраля 2010

по w3

имя узла | Выбирает все дочерние узлы именованного узла

...