public function getRowsFromXml($xml, $parent = 'sh')
    {
        $this->error = '';
        $values = array();
        
        $xmlobj = @simplexml_load_string($xml);
        if (!$xmlobj instanceof \SimpleXMLElement) {
            /* bad xml returned*/
            $this->error = "Can't read output xml";
            return false;
        }
        
        // get all rows of data
        $params = $xmlobj->xpath("/script/$parent/row");
        
        // get data for each row found.
        foreach ($params as $simpleXMLElement) {
            // If hex, get data from script->$parent->hex
            // Then can un-hex (pack) that and do simplexml load string on it, and proceed as below afterward.
            // Examples from XMLSERVICE documentation: http://174.79.32.155/wiki/index.php/XMLSERVICE/XMLSERVICECCSID
            // if hex info was sent back
            
            //  <sh rows='on' hex='on' before='819/37' after='37/819'>
            //      <row><hex>746F74616C2031363636313034</hex></row>
            //  </sh>
                
            
            /*  <cmd exec='rexx' hex='on' before='819/37' after='37/819'>
            *       <success><![CDATA[+++ success RTVJOBA USRLIBL(?) SYSLIBL(?)]]></success>
            *       <row><data desc='USRLIBL'><hex><![CDATA[5147504C20202020202020]]></hex></data></row>
            *       <row><data desc='SYSLIBL'><hex><![CDATA[5153595320202020202020]]></hex></data></row>
            *   </cmd>
            */
            
            
            // if there's a data element, go down one level to it (->data).
            $element = (isset($simpleXMLElement->data)) ? $simpleXMLElement->data : $simpleXMLElement;
            
            // if a hex tag is present, de-hex (pack) the data inside that hex tag; otherwise, use the outer element's value directly.
            $data = (isset($element->hex)) ? pack("H*", (string)$element->hex) : (string)$element;
            
            // process data string received, then add to $values array.
            
            // rows will either be from parent 'cmd' or 'sh'.
            if ($parent == 'cmd') {
                // for RTV* commands,
                // attribute 'desc' of data tag will hold the output field name to which the data belongs.
                $outputFieldName = (string) $element->attributes()->desc;
                
                $data = trim($data, " \n"); // trim spaces and end-of-line chars of data that comes from REXX RTV* commands ('cmd')
                
                $values[$outputFieldName] = $data;
            } else {
                // 'sh'
                $values[] = $data; // no particular index 
            }
        }
        
        if (count($params)==0) {
            $this->error = "No rows";
            $params = $xmlobj->xpath("/script/$parent");
            foreach ($params as $simpleXMLElement) {
                if (strstr(((string)$simpleXMLElement),"+++ no output")) {
                    $this->error = "Command does not return output";
                }
                break;
            }
        }
        
        return $values;
    }