[SOLVED] Php inner loop problem with xml and continue

Issue

Having this xml

    $xml_text = "<file>
  <record>
    <name>A</name>
    <total_parts>2</total_parts>
    <value>25</value>
    <part>2</part>
  </record>
  <record>
    <name>D</name>
    <total_parts>1</total_parts>
    <value>30</value>
    <part>1</part>
  </record>
  <record>
    <name>B</name>
    <total_parts>1</total_parts>
    <value>75</value>
    <part>1</part>
  </record>
  <record>
    <name>A</name>
    <total_parts>2</total_parts>
    <value>80</value>
    <part>1</part>
  </record>
  <record>
    <name>T</name>
    <total_parts>1</total_parts>
    <value>1</value>
    <part>1</part>
  </record>
  <record>
    <name>Z</name>
    <total_parts>1</total_parts>
    <value>3</value>
    <part>1</part>
  </record>
</file>";

Then $xml:

$xml =  simplexml_load_string($xml_text);

If I want to extract for each <name> the list of <value> respecting <part> order (exept T):

foreach ($xml as $record) {
    $print = '';
    if ($record->total_parts == 1) {
        $print .= $record->name . ": " . $record->value;
    } else {
        $print .= $record->name . ": ";
        for ($i=1;$i<=$record->total_parts;$i++) {
            foreach ($xml as $record_inner) {
                if (($record_inner->name == $record->name) and ($record_inner->part==$i)) {
                    $print .= $record_inner->value . ", ";
                    break;
                }      
            }
            
        }        
    }
    if ($record->name=="T") {
        continue;
    } 
    echo $print;  
    echo "\n"; 
}

This is what I want:

A: 80, 25, 
D: 30
B: 75
A: 80, 25, 
Z: 3

This is the php result:

A: 25, 
D: 30
B: 75
A: 80, 

https://onlinephp.io/c/e5df5

Why in the first inner loop condition name = A and part = 1 doesn’t catch value 80 and in the second inner loop name = A and part = 2 doesn’t catch value 25?
Why after continue to skip T, Z is not considered?

Solution

You can get all the results into a new array.

$xml =  simplexml_load_string($xml_text);
$records = [];
foreach($xml->record as $record) {
    $name = (string)$record->name;
    if('T' === $name) {
        continue;
    }
    $records[$name][(int)$record->part - 1] = (int)$record->value;
}

Which is then

Array
(
    [A] => Array
        (
            [1] => 25
            [0] => 80
        )

    [D] => Array
        (
            [0] => 30
        )

    [B] => Array
        (
            [0] => 75
        )

    [Z] => Array
        (
            [0] => 3
        )

)

and can easily brought to your wanted output

foreach($records as $key => $values) {
    ksort($values, SORT_NUMERIC);
    echo "$key: ", implode(', ', $values), "\n";
}

printing as

A: 80, 25
D: 30
B: 75
Z: 3

I think your expected result is that printed above and not the repeated letters?

Answered By – Markus Zeller

Answer Checked By – Mary Flores (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published.