-
Notifications
You must be signed in to change notification settings - Fork 9
Cookbook XML
Pages has robust support for pulling XML values. The following are different ways to access different parts of an XML file.
If you need a direct full path then GET is used.
<?= data('volume-1/issue-1/tomo-01-069')->get('article/front/journal-meta/journal-title-group/journal-title'); ?>
If there are no other conflicting labels then you can access the value directly using FIND. This is a massive time saver since you don't have to traverse through each level like you do with GET.
<?= data('volume-1/issue-1/tomo-01-069')->find('journal-title'); ?>
If your XML uses attributes then you access the values using the filter for attributes.
<?= data('volume-1/issue-1/JSHD-201800011')->get('article/front/article-meta/article-id')->filter('@attributes', ['pub-id-type' => 'publisher-id']); ?>
<?= data('volume-1/issue-1/JSHD-201800011')->find('subj-group')->filter('@attributes', ['subj-group-type' => 'Article Type'])->subject; ?>
If you are using YAML with XML fallback you can set it to default to YAML, then fall back to XML.
$title = $this->title ?? $this->data('volume-1/issue-1/tomo-01-069')->get('article/front/article-meta/title-group/article-title');
Note: This example is within a function which is why $this-> is added.
If you echo the XML data it will pull it as an array. Pages will then transform it to JSON. This saves a few steps if you are needing to separate the output by content within tags in the XML. For example with this line of XML <aff id="aff1">Departments of <label>1</label>Radiology</aff>
. This example is for a list of affiliations with reference numbers, so I am looping through each of them and constructing the output.
if ( $this->data( $this->article_xml('data-path') )->find('aff') !== '' ) {
foreach ( $this->data( $this->article_xml('data-path') )->find('aff') as $aff ) :
if ( isset( $aff['label'] ) ) {
$sup = "<sup>" . $aff['label'] . "</sup>";
}
$affiliations .= $sup . $aff['@text'];
endforeach;
}
If you want to pull the data and output it as HTML then add ->asHtml to the end.
$abstract = $this->publishing['abstract'] ?? $this->data( $this->article_xml('data-path') )->find('abstract')->toHtml();
If you have CSS in your node you would like to select you can using the select option. This is gonna return a nodelist, however there are plans to update it to a string in the future.
$list = data('test-xml')->toHtml()->select('affs.aff1');
For the project in these examples the site is set up with volume, issues, and articles within each issue. XML files are organized in this file structure so it is necessary to dynamically pull each XML file according to which article is being viewed. This function has a switch that allows you to pull the path for other reasons or load the XML file by default.
return function( $type = '' )
{
$volume = $this->volume();
$issue = $this->issue();
$prefix = $this->data('site-info')->file_prefix;
$starting_page = $this->page()->publishing['starting_page'];
//Article data
$file_name = sprintf("%s-%02d-%03d", $prefix, $volume, $starting_page);
$file_name = $this->page()->get('file', $file_name);
$data_path = sprintf('volume-%s/issue-%s/%s', $volume, $issue, $file_name);
if ( $type == 'data-path' ) {
$data = $data_path;
} else {
$data = $this->data($data_path);
}
return $data;
};
Commenting on every part of this would take quite a bit of time, but here is a function to transform your XML into XSL. Modify as needed.
use BetterDOMDocument\DOMDoc;
return function()
{
$volume = $this->volume();
$issue = $this->issue();
$prefix = $this->data('site-info')->file_prefix;
$starting_page = $this->page()->publishing['starting_page'];
//Article data
$file_name = sprintf("%s-%02d-%03d", $prefix, $volume, $starting_page);
$file_name = $this->page()->get('file', $file_name);
$data_path = sprintf('volume-%s/issue-%s/%s', $volume, $issue, $file_name);
/* Load XML file in a way str_replace will work on, save as variable, then close file */
$xml_file_path = JPATH_ROOT.'/joomlatools-pages/data/' . $data_path . '.xml';
$xml_file_temp = fopen( $xml_file_path, 'r');
$xml_content = fread($xml_file_temp, filesize( $xml_file_path ));
fclose($xml_file_temp);
/* Replacing content in XML for better HTML output with XSL */
// Trim whitespace
$xml_updated_content = preg_replace("/>s+</", "><", $xml_content);
// Change URL to images
$base = ltrim($this->getObject('request')->getBaseUrl()->getPath(), '/');
$xml_updated_content = str_replace('xlink:href="assets', 'xlink:href="'.$base.'/joomlatools-pages/assets', $xml_content);
// Make sure there is space between first and last names
$xml_updated_content = str_replace("</surname><given-names>", "</surname> <given-names>", $xml_updated_content);
$xml_updated_content = str_replace("</given-names><suffix>", "</given-names> <suffix>", $xml_updated_content);
$xml = new DOMDocument('1.0', 'UTF-8');
$xml->loadXml( $xml_updated_content );
/* Time for some XSL! */
$xsl = new DOMDocument('1.0', 'UTF-8');
$xsl->loadXml(file_get_contents(JPATH_ROOT.'/joomlatools-pages/layouts/xsl/jats-html-mod.xsl'));
$proc = new XSLTProcessor();
$proc->importStyleSheet($xsl); // attach the xsl rules
$html = $proc->transformToXML($xml);
return $html;
};
Got a question or need help? We have a forum on Github Discussions where you can get in touch with us.