/**
  * Constructor takes a PCML string and converts to an array-based old toolkit data description string.
  *
  * @param string $pcml The string of PCML
  * @param Toolkit $connection connection object for toolkit
  * @throws \Exception
  */
 public function __construct($pcml, Toolkit $connection)
 {
     $this->setConnection($connection);
     // Convert PCML from ANSI format (which old toolkit required) to UTF-8 (which SimpleXML requires).
     $encoding = $connection->getConfigValue('system', 'encoding', 'ISO-8859-1');
     // XML encoding
     /*
      * Look for optionally set <?xml encoding attribute
      * and change encoding if attribute is set and not UTF-8
      * or change encoding if attribute is not set and ini encoding is not UTF-8
      */
     $pcml = trim($pcml);
     $matches = array();
     $regex = '/^<\\?xml\\s.*?encoding=["\']([^"\']+)["\'].*?\\?>/is';
     if (preg_match($regex, $pcml, $matches) && $matches[1] != 'UTF-8') {
         //remove xml-tag
         $pcml = substr($pcml, strlen($matches[0]));
         $pcml = mb_convert_encoding($pcml, 'UTF-8', $matches[1]);
     } elseif ($encoding != 'UTF-8') {
         $pcml = mb_convert_encoding($pcml, 'UTF-8', $encoding);
     }
     //program name is stored as: /pcml/program name="/qsys.lib/eacdemo.lib/teststruc.pgm"
     $xmlObj = new \SimpleXMLElement($pcml);
     // get root node and make sure it's named 'pcml'
     if (!isset($xmlObj[0]) || $xmlObj[0]->getName() != 'pcml') {
         throw new \Exception("PCML file must contain pcml tag");
     }
     $pcmlObj = $xmlObj[0];
     // get program name, path, etc.
     if (!isset($pcmlObj->program) || !$pcmlObj->program) {
         throw new \Exception("PCML file must contain program tag");
     }
     $programNode = $pcmlObj->program;
     $pgmAttrs = $programNode->attributes();
     /**
      * sample:
      * <program name="name"
      * [ entrypoint="entry-point-name" ]
      * [ epccsid="ccsid" ]
      * [ path="path-name" ]
      * [ parseorder="name-list" ]
      * [ returnvalue="{ void | integer }" ]
      * [ threadsafe="{ true | false }" ]>
      * </program>
      */
     // let's focus on name, path, and entrypoint, the only attributes likely to be used here.
     $path = isset($pgmAttrs['path']) ? $pgmAttrs['path'] : '';
     $entrypoint = isset($pgmAttrs['entrypoint']) ? $pgmAttrs['entrypoint'] : '';
     // Note: if entrypoint is supplied, it's the function in a service program. "name" will be the same as entrypoint.
     // if entrypoint is not supplied, name is the actual program name.
     // Therefore, "name" seems somewhat worthless.
     // break up path, separated now by slashes. can be varied lib and pgm.
     // remove the /qsys.lib that may be in front but only if it's simply qualifying another library. qsys may be the actual program library, too.
     $objArray = $this->splitPcmlProgramPath($path);
     if ($objArray['lib']) {
         $pgmName = "{$objArray['lib']}/{$objArray['obj']}";
     } else {
         $pgmName = $objArray['obj'];
     }
     // now add the entrypoint, if any, as a procedure/function.
     if ($entrypoint) {
         // append the entry point enclosed in parentheses.
         $pgmName .= "({$entrypoint})";
     }
     // Now create data description array.
     $dataDescriptionArray = $this->pcmlToArray($xmlObj);
     //Change the encoding back to the one wanted by the user, since SimpleXML encodes its output always in UTF-8
     $pgmName = mb_convert_encoding($pgmName, $encoding, 'UTF-8');
     mb_convert_variables($encoding, 'UTF-8', $dataDescriptionArray);
     // call parent's constructor with:
     //$descObj = new DataDescriptionPcml($description, $connection);
     parent::__construct($pgmName, $dataDescriptionArray, $connection);
 }