Create XML files on post edit screen

If you’re using XML to send Ajax requests, then WP has something built in:

$response = new WP_Ajax_Response();
$response->add( array( 
     // This is the parent elements name
     'what' => 'xml_parent_el'
     // 'data' can only pass CDATA
    ,'data' => $foo
     // 'supplemental' can only pass elements with a unique name
    ,'supplemental' => $bar
) );
$response->send();

If it’s about ajax calls, go with JSON.

The problem with this – due to the internal architecture of wp xml ajax – is that you can’t send multiple elements with the same name. WordPress needs an associative array, where keys are the elements name and values are … well the values. So naming those elements keys exactly the same would override the previous element.

<xml_parent_el>
    <single_el attr="whatever a">Value A</single_el>
    <single_el attr="whatever b">Value B</single_el>
    <single_el attr="whatever c">Value C</single_el>
</xml_parent_el>

Your best bet in this case is using the SimpleXML class provided by php.


EDIT: After seeing the paste, here’s the corrected version. Misstypings can be in there.

<?php
$placemarks = Array();

$kml_query = new WP_Query( 'post_type=kml' );
while ( $kml_query->have_posts() )
{
    $kml_query->the_post();
    if( get_field('marker_datas') )
    {
        while( the_repeater_field('marker_datas') ) 
        {
            $placemarks[ the_sub_field_return('placemark_name') ] = array(
                 'description'  => the_sub_field_return( 'placemark_text' )
                ,'styleUrl'     => the_sub_field_return( 'placemark_style_id' )
                ,'coordinates'  => the_sub_field_return( 'placemark_coordinates' )
            );
        }
    }
}

// Document
$xmlDoc = new DOMDocument();

// Root element
$root = $xmlDoc->appendChild( $xmlDoc->createElement("Document") );

foreach( $placemarks as $name => $data )
{
    // Tag
    $markerTag = $root->appendChild( $xmlDoc->createElement("Placemark") );

    $markerTag->appendChild( $xmlDoc->createElement( "Name", $name ) );

    $markerTag->appendChild( $xmlDoc->createElement( "Description", $data['description'] ) );

    $markerTag->appendChild( $xmlDoc->createElement("styleUrl", $data['styleUrl'] ) );

    // Coordinates
    $coordTag = $markerTag->appendChild( $xmlDoc->createElement( "Point" ) );
    $coordTag->appendChild( $xmlDoc->createElement( "coordinates", $data['coordinates'] ) );
}

header("Content-Type: text/plain");

// make the output pretty (later)
# $xmlDoc->formatOutput = true;

echo $xmlDoc->saveXML();

EDIT: The above snippet works just as expected. I was using the repeater function of the plugin called Advanced Custom Fields and since it echoes the field’s values, a new function had to be added to the plugin which instead of echoing the values, simply returns them:

function the_sub_field_return($field_name, $field = false)
{
$value = get_sub_field($field_name, $field);
if(is_array($value))
{
    $value = implode(', ',$value);
}
return $value;
}

If you are happen to use the same plugin for a similar project don’t forget to add the above function to api.php file located in the plugin’s directory.