首页 > 解决方案 > SimpleXML - 如何列出随机子级列表的属性?

问题描述

我有一些有多个孩子的 xml。他们的名字是已知的,数量和顺序是未知的。在这种情况下,它们可以是 FreeRide 或 SteadyState。

我需要保留它们的顺序,然后提取 Duration 和 Power 的属性。

<?php
$xml='<workout_file>
    <workout>
       <FreeRide Duration="300" Power="1.3"/>
        <SteadyState Duration="300" Power="0.55"/>
        <FreeRide Duration="10"  Power="1.2"/>
        <SteadyState Duration="180" Power="0.55"/>
        <FreeRide Duration="10"  Power="1.1"/>
        <SteadyState Duration="120" Power="0.55"/>
    </workout>
</workout_file>';

$xml=simplexml_load_string($xml);

$count = 0;
foreach($xml->workout->children() as $node ){
    $type = $node->getName();
    echo $type." position: ".$count."<br>";
    $count++;

    //Get Attributes
    //$attr =  $xml->workout->$$type[$count]->attributes(); //Doesn't work Undefined variable: FreeRide
    //echo "Duration: ".$attr['Duration']."<br>";
    //echo "Power: ".$attr['Power']."<br>";
}

我可以使用此代码列出孩子以及他们的位置。但是我不确定如何获取属性,因为不知道确切的子名称(它们可以按任何顺序排列)。

注意:这仅列出了 FreeRide 儿童: $attr = $xml->workout->FreeRide[$count]->attributes();

如何以正确的顺序获取孩子、持续时间和功率的列表?

标签: phpattributessimplexmlchildren

解决方案


这是使用DOM而不是 SimpleXML 的一个很好的例子。根据我的经验,除了最基本的情况外,SimpleXML 通常比 DOM 更难使用。

<?php
$xml='<workout_file>
    <workout>
       <FreeRide Duration="300" Power="1.3"/>
        <SteadyState Duration="300" Power="0.55"/>
        <FreeRide Duration="10"  Power="1.2"/>
        <SteadyState Duration="180" Power="0.55"/>
        <FreeRide Duration="10"  Power="1.1"/>
        <SteadyState Duration="120" Power="0.55"/>
    </workout>
</workout_file>';

//Instantiate a DOMDocument and load our XML
$doc = new DOMDocument();
$doc->loadXML($xml);

// Instantiate DOMXpath with our document
$xpath = new DOMXPath($doc);

//Get all of our workout elements and iterate through them
$workoutElements = $xpath->query('/workout_file/workout');
foreach($workoutElements as $currElement)
{
    //Iterate through the children
    $count = 0;
    foreach($currElement->childNodes as $currIntervalNode)
    {
        /*
         * Since we're going through ALL of the children, some of them will be whitespace nodes we don't care about,
         * so only look at nodes with attributes
         */
        if($currIntervalNode->hasAttributes())
        {
            // the nodeName attribute is the tag name
            $type = $currIntervalNode->nodeName;

            // Pull out the attribute vaules by name
            $duration = $currIntervalNode->getAttribute('Duration');
            $power = $currIntervalNode->getAttribute('Power');

            echo 'Position: '.$count++.'<br>'.PHP_EOL;
            echo 'Type: '.$type.'<br>'.PHP_EOL;
            echo 'Duration: '.$duration.'<br>'.PHP_EOL;
            echo 'Power: '.$power.'<br>'.PHP_EOL;
        }
    }
}

推荐阅读