Search code examples
phpxmlcodeignitersimplexml

SimpleXMLElement XML displays as plain text after CI3 to CI4 upgrade


I am upgrading a page from CI3 to CI4. The page has a button to open a new tab which displays XML data. For some reason the CI4 version is showing the XML as plain text. I copied the source of each of the XML pages and compared them, and the only difference I see are the URLs (one page points to production and one to development). The CI4 page does seem to be formatted as XML in the source code. Why isn't the CI4 page showing as formatted XML?

Link to CI3 XML: https://www.uvm.edu/femc/data/archive/project/bear-brook-watershed-maine/dataset/vegetation-size-categories-corresponding-plot-size/eml_xmlview

Link to CI4 'XML': https://dev.vmc.w3.uvm.edu/xana/CI4/data/archive/project/bear-brook-watershed-maine/dataset/vegetation-size-categories-corresponding-plot-size/eml_xmlview

Here is the code used to create the CI4 page:

in the controller:

    public function eml_xmlview($projecttitle = NULL, $datasettitle = NULL) {

        //Get project and dataset ids from web title, if no match show 404
        $pid=$this->common->get_itemid('project', $projecttitle);
        $did=$this->common->get_itemid('dataset', $datasettitle);
          if($pid==-1){
            show_404();
        }
        
        $published=($this->common->check_publish('tblProject', 'fldPublish','pkProjectID',$pid) AND $this->common->check_publish('tblDataset', 'fldPublishMetadata','pkDatasetID',$did));
        //Check if the person coming to the management section is allowed to manage this particular project
        $canmanage=$this->dataset_model->can_manage_dataset($pid,$did,'permission_project_datasets'); //Check whether person logged in can view unpublished data
        //Find out if this project should be hidden - basically, check if the project is published, or the person is admin, or the person can manage it
        $show=($published OR $canmanage);
        if(!$show){
           show_404();
        }
        
        

        $dataset = $this->dataset_model->get_dataset($pid, $did);
        $project = (ENVIRONMENT=="production") ? $this->project_model->get_projectverbose($pid) : $this->project_model->get_projectverbose($pid, FALSE);  
        $fields = $this->dataset_model->get_fields($did);
        $version = 1; //Placeholder in case we want to add version to package ids later
        if (!empty($project)){
            $project=array_pop($project);
        }
              
       
        $emlstart = <<<XML
<eml:eml system="vmc"
xmlns:eml="eml://ecoinformatics.org/eml-2.1.1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="eml://ecoinformatics.org/eml-2.1.1 eml.xsd"></eml:eml>
XML;
        
        $sxe = new SimpleXMLElement($emlstart);
        $sxe->addAttribute('packageId' , 'vmc.' . $pid . '.' . $did.'.'.$version);

            $emldata = $sxe->addChild('dataset');
                $pbl = $emldata->addChild('publisher');
                    $mtp = $pbl->addChild('metadataProvider');
                        $mtp->addChild('organizationName','Forest Ecosystem Monitoring Cooperative');
                        $mtp->addChild('phone','(802) 656-0683');
                        $mtp->addChild('electronicMailAddress','[email protected]');
                        $mtp->addChild('onlineUrl','www.uvm.edu/femc');
                            $adr = $mtp->addChild('address');
                            $adr->addChild('deliveryPoint','705 Spear Street');
                            $adr->addChild('city','South Burlington');
                            $adr->addChild('administrativeArea','Vermont');
                            $adr->addChild('postalCode','05403');
                            $adr->addChild('country','United States of America');
                //Add project organizations        
                $orgsQry = $this->db->query("SELECT * FROM (SELECT * FROM tblOrganization 
                                            JOIN tblProjectOrganization on tblOrganization.pkOrganizationID = tblProjectOrganization.fkOrganizationID
                                            WHERE fkProjectID = $pid) t 
                                            GROUP BY t.fkOrganizationID, t.enuOrganizationRole
                                            ORDER BY enuOrganizationRole, fldStartDate;");        
                $orgrolesAr = array();
                foreach($orgsQry->getResult() as $row) {  
                    $orgrolesAr["$row->enuOrganizationRole"][] = "$row->fldName1 $row->fldName2";
                }

                foreach($orgrolesAr as $role=>$orgAr) {
                    $ap=$emldata->addChild('associatedParty');

                    foreach($orgAr as $index=>$orgName) {
                        $ap->addChild('organizationName',$this->common->sanitizeForXML($orgName));
                    }
                    $ap->addChild('role',$role);
                }
            
                            
                //Project-level 
                if($project['enuProjectType'] == 'research'){
                    $prj = $emldata->addChild('researchProject');
                }
                else{
                    $prj = $emldata->addChild('project');
                }
                $prj->addChild('title', $this->common->sanitizeForXML($project['fldProjectName']));
                $prj->addChild('abstract')->addChild('para', $this->common->sanitizeForXML($project['fldProjectDescription']));  
                $prj->addChild('shortName',$this->common->sanitizeForXML($project['fldProjectName']));
                    $prs = $prj->addChild('personnel');
                    if(!empty($project['people'])){
                        foreach($project['people'] as $person){ 
                            if($person['enuRole']=='principal-investigator'){
                                $prn = $prs->addChild('principalInvestigator');
                            }
                            else{
                                $prn = $prs->addChild('contentProvider');
                            }
                                $prn->addChild('surName',$this->common->sanitizeForXML($person['fldLastName']));
                                $prn->addChild('givenName',$this->common->sanitizeForXML($person['fldFirstName']));      
                        }
                    }
                    if(!empty($project['tags'])){
                        $kws = $prj->addChild('keywordSet');
                        foreach($project['tags'] as $tag){
                            $kws->addChild('keyword',$this->common->sanitizeForXML($tag['fldTag']));
                        }
                    }  
             
                //Dataset-level
                $dataTable = $emldata->addChild('dataTable');
                $dataTable->addChild('title', $this->common->sanitizeForXML($dataset['fldName']));
                    $cvr = $dataTable->addChild('coverage');
                    $cvr->addAttribute('scope','document');
                        $tmp = $cvr->addChild('temporalCoverage');
                        $tmp->addAttribute('scope','document');
                            $rng = $tmp->addChild('rangeOfDates');
                                if($dataset['fldStartDate'] && $dataset['fldStartDate'] != '0000-00-00'){
                                    $rng->addChild('beginDate')->addChild('calendarDate',$dataset['fldStartDate']);
                                }                               
                                if($dataset['fldEndDate'] && $dataset['fldEndDate'] != '0000-00-00'){
                                    $rng->addChild('endDate')->addChild('calendarDate',$dataset['fldEndDate']);
                                }  
                $dataTable->addChild('description',$this->common->sanitizeForXML($dataset['fldDescription']));
                $dataTable->addChild('purpose',$this->common->sanitizeForXML($dataset['fldPurpose']));
                $dataTable->addChild('shortName',$this->common->sanitizeForXML($dataset['fldDatabaseTableName']));
                    $phy = $dataTable->addChild('physical');
                        $phy->addChild('objectName','VMC.' . $pid . '.' . $did);
                            $dfo = $phy->addChild('dataFormat');
                            $dfo->addChild('formatName','mySQL');
                        $phy->addChild('citation',$this->common->sanitizeForXML($dataset['fldDatasetCitation']));
                        $phy->addChild('distibution')->addChild('online')->addChild('url', site_url('data/archive/project/'.$this->common->sanitizeForXML($project['fldWebTitle']).'/dataset/'.$this->common->sanitizeForXML($dataset['fldWebTitle'])));
                    $atl = $dataTable->addChild('attributeList');
                        foreach($fields as $field){
                            $att = $atl->addChild('attribute');
                                $att->addChild('attributeName',$this->common->sanitizeForXML($field['fldFieldName']));
                                if($field['fldCaption']){
                                    $att->addChild('attributeLabel',$this->common->sanitizeForXML($field['fldCaption']));
                                }
                                if($field['fldFieldDescription']){
                                    $att->addChild('attributeDefinition',$this->common->sanitizeForXML($field['fldFieldDescription']));
                                }
                                if($field['enuDataType']){
                                    $att->addChild('storageType',$this->common->sanitizeForXML($field['enuDataType']));
                                }
                                if($field['enuMeasurementType']){
                                    $mst = $att->addChild('measurementType');
                                        $typ = $mst->addChild(strtolower($this->common->sanitizeForXML($field['enuMeasurementType'])));
                                            if($field['enuUnit']){
                                                $typ->addChild('unit')->addChild('standardUnit',$this->common->sanitizeForXML($field['enuUnit']));
                                            }
                                            if($field['fldPrecision']){
                                                $typ->addChild('precision',$this->common->sanitizeForXML($field['fldPrecision']));
                                            }
                                            if($field['enuFormatString']){
                                                $typ->addChild('formatString',$this->common->sanitizeForXML($field['enuFormatString']));
                                            }
                                            if($field['enuNumberType']){
                                                $typ->addChild('numericDomain')->addChild('numberType',$this->common->sanitizeForXML($field['enuNumberType']));
                                            }
                                                if($field['fldMinimum'] || $field['fldMaximum']){
                                                    $bdg = $typ->addChild('BoundsGroup');
                                                        $bds = $bdg->addChild('bounds');
                                                        $bds->addChild('minimum',$field['fldMinimum']);
                                                        $bds->addChild('maximum',$field['fldMaximum']);
                                                }
                                }
                                if($field['fldEnumList'] && $field['fkLookupID']){
                                    $list = $this->dataset_model->get_list($field['fkLookupID']);
                                    if(!empty($list)){
                                        $grouplist=array();
                                        list($grouplist['list'],$grouplist['listtype'],$grouplist['listname'])=$list;
                                    }
                                    switch ($grouplist['listtype']){
                                        case "custom":
                                            $enu = $att->addChild('enumeratedDomain');
                                            foreach($grouplist['list'] as $pairing){
                                                $cdd = $enu->addChild('codeDefinition');
                                                    $cdd->addChild('code', $this->common->sanitizeForXML($pairing['fldItem']));
                                                    $cdd->addChild('definition', $this->common->sanitizeForXML($pairing['fldDescription']));
                                            }
                                            break;
                                        case "species":
                                            $enu = $att->addChild('enumeratedDomain');
                                            $speciesCoverage = $dataTable->addChild('coverage');
                                            $tmp = $speciesCoverage->addChild('taxonomicCoverage');
                                            foreach($grouplist['list'] as $pairing){
                                                $cdd = $enu->addChild('codeDefinition');
                                                    $cdd->addChild('code', $this->common->sanitizeForXML($pairing['fldOriginalCode']));
                                                    $cdd->addChild('definition', $this->common->sanitizeForXML($pairing['enuTaxonomicSystem'].' #'.$pairing['fldTaxonomicID'].', '.$pairing['fldCommonName'].' ('.$pairing['fldGenus'].' '.$pairing['fldSpecies'].')'));
                                            }
                                            

                                            break;
                                        case "location":
                                            $enu = $att->addChild('enumeratedDomain');
                                            foreach($grouplist['list'] as $pairing){
                                                $cdd = $enu->addChild('codeDefinition');
                                                    $cdd->addChild('code', $this->common->sanitizeForXML($pairing['fldOriginalCode']));
                                                    if (!empty($pairing['descLocationType'])){
                                                        $cdd->addChild('definition', $this->common->sanitizeForXML($pairing['descLocationType'].' '.$pairing['fldDescription']));
                                                    }else{
                                                        $cdd->addChild('definition', $this->common->sanitizeForXML($pairing['fldDescription']));
                                                    }
                                            }
                                            break;
                                        default:
                                            break;
                                            
                                    }
                                }
                        }
                //$dataTable->addChild('license',$dataset['enuDataLicense']);
                
        $sxe->saveXML();       
        $data['sxe'] = $sxe->asXML();
        $data['dump']=false;
        echo view('project/dataset/eml_xmlview', $data);
    }

in the view:

<?php 
if(!$dump){
    header ("Content-Type:text/xml");    
}

echo $sxe
?>

Solution

  • Use CI4 to set headers: https://codeigniter4.github.io/userguide/outgoing/response.html#setting-headers

    I added the following to the controller and that fixed it!

    $this->response->setHeader('Content-Type', 'text/xml');