XML Job Listing Feed

This is a custom post type to create an Indeed-compliant XML job feed for propagating job listings to any site using this format. It draws data from a meta query against a custom data structure built with Toolset Types.


feed-career-searches.php:
<?php ob_clean();
// Template name: Searches Feed
?><?php
header('Content-Type: text/xml');
echo '<?xml version="1.0" encoding="utf-8"?>';
?>

<source>
<publisher><?php bloginfo('name'); ?></publisher>
<publisherurl><?php bloginfo('url'); ?></publisherurl>
<lastBuildDate>Tue, 4 Apr 2017 21:30:00 GMT</lastBuildDate>

<?php

function utf8_for_xml($string) {
    return preg_replace('/[^\x{0009}\x{000a}\x{000d}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}]+/u', ' ', $string);
}

?>

<?php

$searches = get_posts([
    'post_type' => 'career_searches',
    'posts_per_page' => -1,

    'tax_query' => [
        [
            'taxonomy' => 'search_categories',
            'field' => 'slug',
            'terms' => 'current'
        ],

        [
            'taxonomy' => 'search_categories',
            'field' => 'slug',
            'terms' => 'completed',
            'operator' => 'not in'
        ]
    ]
]);

?>

<?php foreach ($searches as $search): ?>
    <?php
    $permalink = get_post_permalink($search->ID);
    $job_id = get_post_meta($search->ID, 'wpcf-job-id', true);
    $employer = get_post_meta($search->ID, 'wpcf-employer', true);
    $city = get_post_meta($search->ID, 'wpcf-city', true);
    $state = get_post_meta($search->ID, 'wpcf-state-province', true);
    $country = get_post_meta($search->ID, 'wpcf-country', true);

    $job_title = get_the_title($search->ID);
    $job_industry = get_post_meta($search->ID, 'wpcf-category', true);
    $job_market = get_post_meta($search->ID, 'wpcf-market', true);
    $job_location = $city . ', ' . $state . ', ' . $country;

    $content =
        '<p>' .
        'Job Title: ' . $job_title . '<br/>' .
        'Industry: ' . $job_industry . '<br>' .
        'Market: ' . $job_market . '<br>' .
        'Location: ' . $job_location . '/br>' .
        '</p>' . $search->post_content;

    $content = apply_filters('the_content', $content);
    $content = str_replace(']]>', ']]&gt;', $content);
    $content = utf8_for_xml('<![CDATA[' . $content . ']]>');

    $terms = get_the_terms($search->ID, 'wpcf-category');
    ?>

    <job>
        <jobid><![CDATA[<?= $job_id ?>]]></jobid>
        <title><![CDATA[<?= $job_title ?>]]></title>

        <?php the_custom_value('date', get_the_date('r'), 'date', '', true) ?>

        <referencenumber><![CDATA[<?= $post->ID ?>]]></referencenumber>
        <url><![CDATA[<?= $permalink ?>]]></url>
        <company><![CDATA[<?= $employer ?>]]></company>
        <city><![CDATA[<?= $city ?>]]></city>
        <country><![CDATA[<?= $country ?>]]></country>

        <?php the_custom_value('description', $content, 'string', '', true); ?>

        <category><![CDATA[<?= $job_industry ?>]]></category>
    </job>
<?php endforeach ?>
</source>