Skip to content
Johan Janssens edited this page Apr 8, 2021 · 19 revisions

Pages has robust support for pulling XML values using the Data API. The following are different ways to access different parts of an XML file.

Get

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'); ?>

Find

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'); ?>

Attributes

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; ?>

Adding Defaults

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.

Output options

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();

Selecting node by CSS

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');

Creating dynamic paths to XML

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;
};