admin管理员组

文章数量:1122846

I need to create an endpoint that when called returns an XML with the products of the store. I have the XML generated, but I don't know how to make the endpoint return it in XML format, because now it returns it in JSON format, and being an XML, it does not return it well.

This is my code:

<?php

/**
* Plugin Name: example
* Plugin URI: /
* Description: example
* Version: 1.0
* Author: example
* Author URI: /
*/

function smg_feed() {
   $args = array( 'post_status' => 'publish', numberposts => -1 );
   $products = wc_get_products($args);

   $xml_header = '<?xml version="1.0" encoding="UTF-8"?><Document></Document>';
   $xml = new SimpleXMLElement($xml_header);

   foreach($products as $product) {
       $data = $product->get_data();
       $sku = $data['sku'];
       $categoriasNombres = array();
       $subcategoriasNombres = array();
       foreach( wp_get_post_terms( $data['id'], 'product_cat' ) as $term ){
           if( $term ){
               if ($term->name == 'XXXX' || $term->name == 'YYYY') {
                   array_push($categoriasNombres, $term->name);
               } else {
                array_push($subcategoriasNombres, $term->name);
               }
           }
       }
       $categoriasNombres = implode(',', $categoriasNombres);
       $subcategoriasNombres = implode(',', $subcategoriasNombres);
       $propiedadesNombres = array();
       foreach( wp_get_post_terms( $data['id'], 'product_tag' ) as $term ){
           if( $term ){
               array_push($propiedadesNombres, $term->name);
           }
       }
       $propiedadesNombres = implode(',', $propiedadesNombres);
       $nombre = $data['name'];
       $formatosNombres = array();
       foreach( wp_get_post_terms( $data['id'], 'pa_formato' ) as $term ){
           if( $term ){
               array_push($formatosNombres, $term->name);
           }
       }
       $formatosNombres = implode(',', $formatosNombres);
       $metaData = $data['meta_data'];

       foreach($metaData as $item) {
           if ($item->key == '_role_based_price') {
               $obj = $item->value;
               $precio = $obj['api1']['regular_price'];
               $precioEspecial = $obj['api2']['regular_price'];
           }
       }

       $row = $xml->addChild('row');
       $row->addChild('sku', $sku);
       $row->addChild('categorias', $categoriasNombres);

       $row->addChild('subcategorias', $subcategoriasNombres);
       $row->addChild('propiedades', $propiedadesNombres);
       $row->addChild('nombre', $nombre);
       // $row->addChild('imagen', );

       $row->addChild('formatos', $formatosNombres);
       $row->addChild('precio', $data['regular_price']);
       $row->addChild('precio_especial', $precioEspecial);
   }

   $output = $xml->asXML();

   return $output;
}

add_action('rest_api_init', function() {

   register_rest_route('smg/v1', 'feed', [
       'methods' => 'GET',
       'callback' => 'smg_feed',
   ]);

});

But when I make the call to the endpoint what it returns is this:

"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n
<Document>
<row>
<sku\/>
<categorias>Nutrici\u00f3n<\/categorias>
<subcategorias>Nutridefense Plus<\/subcategorias>
<propiedades>todo<\/propiedades>
<nombre>NutriDefense plus<\/nombre>
<formatos\/>
<precio>29,90<\/precio>
<precio_especial>26,52<\/precio_especial>
<\/row>
<\/Document>\n"

How can I make it return it in XML format? Thank you very much.

Regards.

I need to create an endpoint that when called returns an XML with the products of the store. I have the XML generated, but I don't know how to make the endpoint return it in XML format, because now it returns it in JSON format, and being an XML, it does not return it well.

This is my code:

<?php

/**
* Plugin Name: example
* Plugin URI: https://www.example.es/
* Description: example
* Version: 1.0
* Author: example
* Author URI: https://www.example.es/
*/

function smg_feed() {
   $args = array( 'post_status' => 'publish', numberposts => -1 );
   $products = wc_get_products($args);

   $xml_header = '<?xml version="1.0" encoding="UTF-8"?><Document></Document>';
   $xml = new SimpleXMLElement($xml_header);

   foreach($products as $product) {
       $data = $product->get_data();
       $sku = $data['sku'];
       $categoriasNombres = array();
       $subcategoriasNombres = array();
       foreach( wp_get_post_terms( $data['id'], 'product_cat' ) as $term ){
           if( $term ){
               if ($term->name == 'XXXX' || $term->name == 'YYYY') {
                   array_push($categoriasNombres, $term->name);
               } else {
                array_push($subcategoriasNombres, $term->name);
               }
           }
       }
       $categoriasNombres = implode(',', $categoriasNombres);
       $subcategoriasNombres = implode(',', $subcategoriasNombres);
       $propiedadesNombres = array();
       foreach( wp_get_post_terms( $data['id'], 'product_tag' ) as $term ){
           if( $term ){
               array_push($propiedadesNombres, $term->name);
           }
       }
       $propiedadesNombres = implode(',', $propiedadesNombres);
       $nombre = $data['name'];
       $formatosNombres = array();
       foreach( wp_get_post_terms( $data['id'], 'pa_formato' ) as $term ){
           if( $term ){
               array_push($formatosNombres, $term->name);
           }
       }
       $formatosNombres = implode(',', $formatosNombres);
       $metaData = $data['meta_data'];

       foreach($metaData as $item) {
           if ($item->key == '_role_based_price') {
               $obj = $item->value;
               $precio = $obj['api1']['regular_price'];
               $precioEspecial = $obj['api2']['regular_price'];
           }
       }

       $row = $xml->addChild('row');
       $row->addChild('sku', $sku);
       $row->addChild('categorias', $categoriasNombres);

       $row->addChild('subcategorias', $subcategoriasNombres);
       $row->addChild('propiedades', $propiedadesNombres);
       $row->addChild('nombre', $nombre);
       // $row->addChild('imagen', );

       $row->addChild('formatos', $formatosNombres);
       $row->addChild('precio', $data['regular_price']);
       $row->addChild('precio_especial', $precioEspecial);
   }

   $output = $xml->asXML();

   return $output;
}

add_action('rest_api_init', function() {

   register_rest_route('smg/v1', 'feed', [
       'methods' => 'GET',
       'callback' => 'smg_feed',
   ]);

});

But when I make the call to the endpoint what it returns is this:

"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n
<Document>
<row>
<sku\/>
<categorias>Nutrici\u00f3n<\/categorias>
<subcategorias>Nutridefense Plus<\/subcategorias>
<propiedades>todo<\/propiedades>
<nombre>NutriDefense plus<\/nombre>
<formatos\/>
<precio>29,90<\/precio>
<precio_especial>26,52<\/precio_especial>
<\/row>
<\/Document>\n"

How can I make it return it in XML format? Thank you very much.

Regards.

Share Improve this question asked Nov 10, 2020 at 12:02 pmjpmj 631 silver badge3 bronze badges 3
  • How can read this xml format from front end url. What is the url made for display this xml format data. Please let me know. – Heena Commented Feb 18, 2021 at 8:07
  • If you're using the code in the question or Sally's answer then you can see it's registered with register_rest_route('smg/v1', 'feed', ... ); so this will be /wp-json/smg/v1/feed on your site. – Rup Commented Feb 18, 2021 at 9:49
  • ok thanks. @Rup – Heena Commented Feb 18, 2021 at 11:00
Add a comment  | 

2 Answers 2

Reset to default 6

By default, the output returned by your endpoint/callback will always be sent as a JSON-encoded string (and the Content-Type header would also be/contain application/json), so you can't use that callback for sending an XML feed.

However, you can use the rest_pre_serve_request hook if you want your REST API route to serve a different type of content like the XML feed in your case.

So for example, you can do:

  1. Set your callback (smg_feed()) to return the XML data which will be echoed in the maybe_smg_feed() below: (note that the permission_callback should always be set, check the REST API handbook for more details)

    function smg_feed( $request ) {
        // ... your code ...
        return 'your XML data';
    }
    
    add_action( 'rest_api_init', function () {
        register_rest_route( 'smg/v1', 'feed', [
            'methods'             => 'GET',
            'callback'            => 'smg_feed', // make sure it returns an XML string
            'permission_callback' => '__return_true',
        ]);
    });
    
  2. Then send the XML response like so:

    function maybe_smg_feed( $served, $result, $request, $server ) {
        // Bail if the route of the current REST API request is not our custom route.
        if ( '/smg/v1/feed' !== $request->get_route() ||
            // Also check that the callback is smg_feed().
            'smg_feed' !== $request->get_attributes()['callback'] ) {
            return $served;
        }
    
        // Send headers.
        $server->send_header( 'Content-Type', 'text/xml' );
    
        // Echo the XML that's returned by smg_feed().
        echo $result->get_data();
    
        // And then exit.
        exit;
    }
    add_filter( 'rest_pre_serve_request', 'maybe_smg_feed', 10, 4 );
    

Alternatively (as I mentioned in the original answer), without using the REST API (which does work), you can use add_feed() to deliver the XML feed.

( PS: Thanks to @TimothyJacobs for his help/comment. :) )

function smg_feed( $request ) {
 ....
 echo $xml->asXML();
 return new WP_REST_Response( null, 200, ['Content-Type' => 'text/xml'] );
}

本文标签: plugin developmentCustom endpoint that returns an xml