3
<info>
    <form tableid="1">
        <town_id>
            <option value="5102">Moscow</option>
            <option value="2587">London</option>
            <option value="717">Madrid</option>
            <option value="2513">Paris</option>
            <option value="5071">Berlin</option>
        </town_id>
    </form>
</info>

I have such xml and wanna parse it throught simplexml_load_string. Function returns such object:

SimpleXMLElement Object
(
    [form] => SimpleXMLElement Object
        (
            [@attributes] => Array
                (
                    [tableid] => 1
                )

            [town_id] => SimpleXMLElement Object
                (
                    [option] => Array
                        (
                            [0] => Moscow
                            [1] => London
                            [2] => Madrid
                            [3] => Paris
                            [4] => Berlin
                        )

                )

        )

)

I don't have second attributes value from town options. How can I get them? my code:

/** @var SimpleXMLElement $xml */
$xml = simplexml_load_string($data);
if (! is_object($xml)) return FALSE;

print_r($xml);
foreach($xml as $record){
    $attr = $record->attributes();
    $table_id = (int)$attr['tableid'];
   foreach($record as $key => $value){
      //$table_data[$table_id][$key][] = $value['option'];
       print_r($value->attributes());
       print_r($value['option']->attributes());
   }
}

$value is a SimpleXMLElement object, but $value->attributes() and $value['option]->attributes() return empty array.

0

1 Answer 1

4

You can simply iterate the SimpleXMLElement objects by accessing the children with -> operator:

$xml = <<<'XML'
<info>
    <form tableid="1">
        <town_id>
            <option value="5102">Moscow</option>
            <option value="2587">London</option>
            <option value="717">Madrid</option>
            <option value="2513">Paris</option>
            <option value="5071">Berlin</option>
        </town_id>
        <town_id>
            <option value="9343">XTown</option>
        </town_id>
    </form>
</info>
XML;

$items = simplexml_load_string($xml);

foreach ($items as $form) {
    foreach ($form->town_id as $town) {
        foreach ($town->option as $option) {
            $attr = $option->attributes();
            printf("#%d - %s\n", $attr['value'], $option);
        }
    }
}

Output

#5102 - Moscow
#2587 - London
#717 - Madrid
#2513 - Paris
#5071 - Berlin
#9343 - XTown

XPath

Alternatively, use xpath method:

$options = $items->xpath('form/town_id/option');
foreach ($options as $option) {
  $attr = $option->attributes();
  printf("#%d - %s\n", $attr['value'], $option);
}

In this example I used an XPath expression relative to $items (root element, in particular). Adjust the XPath according to your needs. For example, you can fetch all options in the document with //option. Or you might even want to iterate all elements under form having option children:

$containers = $items->xpath('form/*[option]');
foreach ($containers as $c) {
  switch ($c->getName()) {
    case 'town_id':    $label = 'Towns';     break;
    case 'country_id': $label = 'Countries'; break;
    default:
      // Skipping unknown element name
      continue;
  }

  printf("\n%s\n======\n", $label);
  foreach ($c->option as $option) {
    $attr = $option->attributes();
    printf("#%d - %s\n", $attr['value'], $option);
  }
}

Sample Output

Towns
======
#5102 - Moscow
#2587 - London
#717 - Madrid
#2513 - Paris
#5071 - Berlin

Towns
======
#9343 - XTown

Countries
======
#3456 - Russia
#4566 - China
Sign up to request clarification or add additional context in comments.

4 Comments

@WebDev, have you read the example with form/*[option]? The * refers to all elements having option tag. You don't need to know the element names at all. You might even use //*[option]. In the latter case, you need to know only about option.
oh, sorry. I was confused by switch and enumeration all fields. I haven't noticed that you only set labels in switch.
one more question: how can I get options only from block form with tableid=1? Does it exist method such as $items->xpath('form[1]/*[option]'); or $items->xpath('form[2]/*[option]');
@WebDev, 'form[@tableid="1"]/*[option]'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.