PHP / XPath: перебор узлов-предков в XML с использованием SimpleXML - PullRequest
0 голосов
/ 08 января 2011

Мне нужно перебрать узлы Ancestors, чтобы получить соответствующие значения BrowseNodeId и Name. Как мне сделать это с помощью XPath? Я пытаюсь что-то вроде следующего, но это не работает:

//BrowseNode[1]//Ancestors[1]/BrowseNode/BrowseNodeId/text()
//BrowseNode[1]//Ancestors[1]/BrowseNode/Name/text()

Я думаю, что //Ancestors часть XPath на самом деле ищет все дерево XML. Что мне нужно сделать, это посетить каждый узел, чтобы получить необходимые значения. Как мне это сделать? В приведенном ниже примере я хочу: Европа -> История -> Темы -> Книги.

Пример XML:

    <BrowseNode>
        <BrowseNodeId>4952</BrowseNodeId>
        <Name>France</Name>
        <Ancestors>
            <BrowseNode>
                <BrowseNodeId>4935</BrowseNodeId>
                <Name>Europe</Name>
                <Ancestors>
                    <BrowseNode>
                        <BrowseNodeId>9</BrowseNodeId>
                        <Name>History</Name>
                        <Ancestors>
                            <BrowseNode>
                                <BrowseNodeId>1000</BrowseNodeId>
                                <Name>Subjects</Name>
                                <IsCategoryRoot>1</IsCategoryRoot>
                                <Ancestors>
                                    <BrowseNode>
                                        <BrowseNodeId>283155</BrowseNodeId>
                                        <Name>Books</Name>
                                    </BrowseNode>
                                </Ancestors>
                            </BrowseNode>
                        </Ancestors>
                    </BrowseNode>
                </Ancestors>
            </BrowseNode>
        </Ancestors>
    </BrowseNode>

Ответы [ 5 ]

1 голос
/ 08 января 2011

В приведенном ниже примере я хочу: Европа -> История -> Темы -> Книги.

Я думаю, вам нужно:

//Ancestors/BrowseNode/Name

Или просто переберите //Ancestors/BrowseNode результатов и получите Name и BrowseNodeId потомков с любым методом DOM.

0 голосов
/ 08 января 2011

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

// Get top level BrowseNode elements
$browse_nodes = $xml->xpath('//BrowseNodes/BrowseNode');
foreach ($browse_nodes as $browse_node) {
    // Get ancestor BrowseNode elements
    $ancestors = $browse_node->xpath('Ancestors//BrowseNode');
    // Do whatever you like with them! :-)
}
0 голосов
/ 08 января 2011
/BrowseNode/Ancestors//BrowseNode/Name/text()

Будет работать с вами образец.

Однако, он будет искать все узлы, находящиеся после «первого» элемента Ancestors. Реверс и взгляд из глубины BrowseNode сделали бы почти то же самое.

В XSLT жизнеспособной и необходимой альтернативой было бы использование ключей для повышения эффективности.

0 голосов
/ 08 января 2011

Может быть, попытаться найти последний узел, а затем извлечь предков?

<?php

$xml = "
    <BrowseNode>
        <BrowseNodeId>4952</BrowseNodeId>
        <Name>France</Name>
        <Ancestors>
            <BrowseNode>
                <BrowseNodeId>4935</BrowseNodeId>
                <Name>Europe</Name>
                <Ancestors>
                    <BrowseNode>
                        <BrowseNodeId>9</BrowseNodeId>
                        <Name>History</Name>
                        <Ancestors>
                            <BrowseNode>
                                <BrowseNodeId>1000</BrowseNodeId>
                                <Name>Subjects</Name>
                                <IsCategoryRoot>1</IsCategoryRoot>
                                <Ancestors>
                                    <BrowseNode>
                                        <BrowseNodeId>283155</BrowseNodeId>
                                        <Name>Books</Name>
                                    </BrowseNode>
                                </Ancestors>
                            </BrowseNode>
                        </Ancestors>
                    </BrowseNode>
                </Ancestors>
            </BrowseNode>
        </Ancestors>
    </BrowseNode>
";


$sxe = simplexml_load_string($xml);

// Set the target to reach
$target = current($sxe->xpath("//BrowseNode[./BrowseNodeId = '283155']"));

// Get all names from root to target
$names = array_map('strval', $target->xpath('ancestor-or-self::Ancestors/BrowseNode/Name'));
print_r($names);
// Array
// (
//     [0] => Europe
//     [1] => History
//     [2] => Subjects
//     [3] => Books
// )

// Get all ids from root to target
$ids = array_map('strval', $target->xpath('ancestor-or-self::Ancestors/BrowseNode/BrowseNodeId'));
print_r($ids);
// Array
// (
//     [0] => 4935
//     [1] => 9
//     [2] => 1000
//     [3] => 283155
// )

// Final
$combined = array_combine($ids, $names);
print_r($combined);
// Array
// (
//     [4935] => Europe
//     [9] => History
//     [1000] => Subjects
//     [283155] => Books
// )
0 голосов
/ 08 января 2011
$browse_nodes = $xml->BrowseNode;
foreach ($browse_nodes as $browse_node) {
    echo $browse_node->BrowseNodeId.nodeValue;
    echo $browse_node->Name.nodeValue;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...