使用 XMLReader 选择父节点

2022-01-10 00:00:00 xml xpath xml-parsing php

我不得不重写部分程序以使用 XMLReader 选择 XML 文件的部分进行处理.

I had to rewrite part of a programme to use XMLReader to select parts of an XML file for processing.

以这个简化的 XML 为例:

Take this simplified XML as an example:

<odds>
    <sport>
        <region>
            <group>
                <event name="English Championship 2014-15" eventid="781016.1">
                    <bet name="Kazanan" betid="12377108.1">
                        <selection selectionid="52411062.1"/>
                        </selection>
                    </bet>
                </event>
            </group>
        </region>
    </sport>
</odds> 

xpath() 的调用:

$bets = $xml->xpath(
    "//odds/sport/region/group/event/bet/selection[contains(@selectionid,'".$selectionToFind."')]/.."
    );

将选择整个 <bet> 节点及其子节点(<selection> 节点).

would select the whole <bet> node and its children (<selection> nodes).

然而,我的代码只会选择一个具有给定 selectionid 节点:

My code, however, would select only one <selection> node with a given selectionid:

$reader = new XMLReader;
$reader->open('file.xml');

while($reader->read()) {
    $event = $reader->getAttribute($value); 

    if ($event == 781016.1 ) {
        $node = new SimpleXMLElement($reader->readOuterXML());
        var_dump($node);
        break;
    }
}

如何使用 XMLReader 复制 xpath() 的行为,以便我选择 <bet> 节点及其子节点,而不是只有一个 <selection> 孩子?

How can replicate the behaviour of xpath() with XMLReader so that I select the <bet> node and its children and not only one <selection> child?

我想问题归结为:我可以通过一个孩子的属性值来选择整个父节点<bet>,例如?

I guess the question boils down to: Can I select the whole parent node <bet> by the attribute value of a child, e.g. <selection selectionid="[some_value]">?

推荐答案

[忽略SimpleXML方案,低头看XMLReader一个]

[Ignore the SimpleXML solution and look down at the XMLReader one]

我建议使用 SimpleXMLElement::xpath 方法.

I would suggest using the SimpleXMLElement::xpath method.

http://php.net/manual/en/simplexmlelement.xpath.php

$xml = new SimpleXMLElement($xml_string);

/* Search for <a><b><c> */
$result = $xml->xpath("/odds/sport/region/group/event/bet");

$result 将包含 'bet' 注释的所有子级.

$result will contain all children of 'bet' note.

//XMLReader 解决方案 ************************

// XMLReader solution **********************

$reader = new XMLReader;
$reader->open('file.xml');
$parent_element = null;

while($reader->read()) {
    $selectionid = $reader->getAttribute('selectionid'); 

    if ($selectionid == '52411062.1' ) {
        // use the parent of the node with attribute 'selectionid' = '52411062.1'
        $node = $parent_element;
        var_dump($node);
        break;
    }
    elseif ($reader->name === 'bet') { )
    {
        // store parent element
        $parent_element = new SimpleXMLElement($reader->readOuterXML());
    }
}

相关文章