Search code examples
phpxmlsimplexml

Simplexml Add Attribute with many parameter


I try to create following xml line with simple xml and php:

  <stream languageCode="BG" mpegStreamID="0xBD" mpegSubstreamID="0x20"/>
  <stream languageCode="EN" mpegStreamID="0xBD" mpegSubstreamID="0x21"/>
  <stream languageCode="FR" mpegStreamID="0xBD" mpegSubstreamID="0x22"/>

so far I did this in a loop:

foreach($langs as $key => $value)
{
    $this->lang->addAttribute('languageCode', $var1, 'mpegStreamID', '0xBD', 'mpegSubStreamID', '0x2'.$i);
}

but I get following error:

SimpleXMLElement::addAttribute() expects at most 3 parameters, 6 given

Thus I tried this:

    foreach($langs as $key => $value)
    {
        $this->streamLang->addAttribute('languageCode', $var);
        $this->streamLang->addAttribute('mpegStreamID', '0xBD');
        $this->streamLang->addAttribute('mpegSubStreamID', '0x2'.$i);
        $i++;
    }

But get this error:

add Attribute does already exist

The Errors are fairly clear, but I do not know how to create a workaround so to say.


Solution

  • The first error message is self explaining, here some functions that allow you to use a variable count of arguments, but most are not. SimpleXMLElement::addAttribute() expects name, value and optionally a namespace. You have to call it for each attribute you would like to add.

    In the loop you add the 3 attributes to the same node several times. So in the second iteration the attribute does already exists and the call fails.

    Here not enough of you source (obviously it is part of a larger class - you use $this) to say a lot more about it. But here is an complete example:

    $languages = ['BG', "EN", "FR"];
    
    $streams = new SimpleXMLElement('<streams/>');
    foreach ($languages as $index => $language) {
      $stream = $streams->addChild('stream');
      $stream->addAttribute('languageCode', $language);
      $stream->addAttribute('mpegStreamID', '0xBD');
      $stream->addAttribute('mpegSubStreamID', '0x2'.($index + 1));
    }
    
    echo $streams->asXml();
    

    This will look nearly the same if you're using DOM:

    $languages = ['BG', "EN", "FR"];
    
    $document = new DOMDocument();
    $streams = $document->appendChild($document->createElement('streams'));
    foreach ($languages as $index => $language) {
      $stream = $streams->appendChild($document->createElement('stream'));
      $stream->setAttribute('languageCode', $language);
      $stream->setAttribute('mpegStreamID', '0xBD');
      $stream->setAttribute('mpegSubStreamID', '0x2'.($index + 1));
    }
    $document->formatOutput = TRUE;
    echo $document->saveXml();