PHP / XPath:使用SimpleXML迭代XML中的祖先节点

时间:2011-01-08 06:35:27

标签: php xml xpath

我需要遍历Ancestors个节点才能获得相应的BrowseNodeIdName值。我如何使用XPath执行此操作?我正在尝试类似下面的内容,但它不起作用:

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

我认为XPath的//Ancestors部分实际上是在搜索整个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 个答案:

答案 0 :(得分:1)

  

在下面的例子中,我想要:欧洲    - &GT;历史 - &gt;主题 - &gt;书籍。

我认为你需要:

//Ancestors/BrowseNode/Name

或者只是迭代//Ancestors/BrowseNode个结果,并使用任何DOM方法获取NameBrowseNodeId个孩子。

答案 1 :(得分:0)

$browse_nodes = $xml->BrowseNode;
foreach ($browse_nodes as $browse_node) {
    echo $browse_node->BrowseNodeId.nodeValue;
    echo $browse_node->Name.nodeValue;
}

答案 2 :(得分:0)

也许尝试找到最终节点,然后提取是祖先?

<?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
// )

答案 3 :(得分:0)

/BrowseNode/Ancestors//BrowseNode/Name/text()

将与您合作。

但是,它将搜索所有节点descandant到“first”Ancestors元素。从最深的BrowseNode开始反转和观察也会有相同的效果。

在XSLT中,可行且必要的替代方案是使用密钥来提高效率。

答案 4 :(得分:0)

我可能误解了你对你想要的描述,但希望不是。此代码段会查找所有“顶级”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! :-)
}
相关问题