Example: node.save and CCK fields in PHP client code

Last updated on
30 April 2025

Services 6.x-2.x-dev on Drupal 6.14. Uses the XML-RPC for PHP library at http://phpxmlrpc.sourceforge.net/. Thanks to clues from http://drupal.org/node/303285 and the services tester, it includes some code for populating CCK fields ("field_publication", "field_byline", etc.). This is pre-production code for importing articles to a newspaper website, designed to run on the command line. I just left the parseXML() function as an example.

<?php
  require('./xmlrpc-3.0.0.beta/lib/xmlrpc.inc');
  $username = "username";
  $pass = "password";
  $domain = "example.com";
  $publication = "The Daily Drupal";
  $servicehost = "example.com";
  $servicepath = "services/xmlrpc";
  $sessid = "";
  $uid = 0;
  $xmlpath = "/path/to/xml";
  $processdir = "/path/to/processed";
  $successdir = "$processdir/success";
  $failuredir = "$processdir/failure";
  
  // Make initial connection to get a session ID
  $m = new xmlrpcmsg('system.connect', array());
  $c = new xmlrpc_client($servicepath, $servicehost, 80);
  $c->return_type = "phpvals";
  
  $r = &$c->send($m);
  if(!$r->faultCode()){
    $v = $r->value();
    $sessid = ($v['sessid']);
  }else{
    die("An error occurred on system.connect: ".$r->faultString()."\n");
  }

  // Using the session ID from the first connection, log in to the server
  $m = new xmlrpcmsg("user.login",
    array(
      new xmlrpcval($sessid),
      new xmlrpcval($username),
      new xmlrpcval($pass))
  );
	// If login is successful, user object and a new sessid will be returned
  $r = &$c->send($m);
  if(!$r->faultCode()){
    $v = $r->value();
    // Only need uid for our purposes
    $uid = $v['user']['uid'];
    $sessid = $v['sessid'];
  }else{
    die("An error occurred on user.login: ".$r->faultString()."\n");
  }
  
  // Open the XML directory and iterate files
  $dir_handle = @opendir($xmlpath) or die("Unable to open $xmlpath\n");
  
  while ($file = readdir($dir_handle)) 
  {
    // Only get files named *.xml
    if(end(explode(".", $file)) != "xml")
      continue;
    
    // Ignore parsing errors for now and continue
    libxml_use_internal_errors(true);
    $xmldoc = simplexml_load_file("$xmlpath/$file");
    if(!$xmldoc){
      rename("$xmlpath/$file", "$failuredir/$file");
      continue;
    }
    
    // Pass the XML to be parsed and get back a PHP node structure
    $node = parseXML(&$xmldoc);
    // Call the service to create the node
    $nid = createNode($sessid, &$node);
    
    // Move file to success or failure directory
    if($nid > 0){
      rename("$xmlpath/$file", "$successdir/$file");
      print "Node $nid created.\n";
    }
    else{
      rename("$xmlpath/$file", "$failuredir/$file");
    }
  }
  
  closedir($dir_handle);
  
  function parseXML($xmldoc){
    global $publication;
    // Initialize array container for node data
    $node = array();
    
    $node["publication"] = $publication;
    $node["type"] = "story";
    $node["format"] = 2;
    
    $tmp = $xmldoc->xpath("//meta[@name='feed.doc.name']");
    $node["filename"] = trim($tmp[0]['content']);
    
    $tmp = $xmldoc->xpath("//meta[@name='feed.doc.id']");
    $node["docid"] = trim($tmp[0]['content']);
    
    $tmp = $xmldoc->xpath("//meta[@name='cms.section']");
    $node["section"] = trim($tmp[0]['content']);

    $tmp = $xmldoc->xpath("//meta[@name='cms.category']");
    $node["category"] = trim($tmp[0]['content']);

    $tmp = $xmldoc->xpath("//meta[@name='cms.release']");
    $node["releasedate"] = trim($tmp[0]['content']);

    $tmp = $xmldoc->xpath("//meta[@name='cms.expire']");
    $node["expiredate"] = trim($tmp[0]['content']);

    $tmp = $xmldoc->xpath("//meta[@name='position.rank']");
    $node["positionrank"] = trim($tmp[0]['value']);
    
    $tmp = $xmldoc->xpath("//pubdata");
    $node["positionsection"] = trim($tmp[0]['position.section']);
    $node["positionsequence"] = trim($tmp[0]['position.sequence']);
    $node["pubdataname"] = trim($tmp[0]['name']);
    
    $node["headline"] = $xmldoc->body->{'body.head'}->hedline->hl1;
    
    $node["subhead"] = $xmldoc->body->{'body.head'}->hedline->hl2;
    
    $node["byline"] = $xmldoc->body->{'body.head'}->byline->person;
    
    $node["bylinecredit"] = $xmldoc->body->{'body.head'}->bylinecredit->site;
    
    // Try to access the body in different ways to account for screwy XML
    $tmp = $xmldoc->body->{'body.content'};
    foreach($tmp->children() as $element){
      if($element->getName() !== "media")
        $node["body"] .= $element->asXML();
    }
    
    if($node["body"] === "")
      $node["body"] = $xmldoc->body->{'body.content'};
    
    // Ampersands are encoded but need to be unencoded for other HTML characters
    $node["body"] = preg_replace("/&amp;/", "&", $node["body"]);
    
    return $node;
  }
  
  // Handle node.save and CCK fields
  function createNode($sessid, $node){
    global $c, $uid, $username;
    
    $edit = new xmlrpcval(
      array(
        "uid" => new xmlrpcval($uid, "int"),
        "name" => new xmlrpcval($username),
        "type" => new xmlrpcval($node["type"]),
        "format" => new xmlrpcval($node["format"], "int"),
        "title" => new xmlrpcval($node["headline"]),
        "body" => new xmlrpcval($node["body"]),
        "field_publication" => new xmlrpcval(array(new xmlrpcval(array("value" => new xmlrpcval($node["publication"])), "struct")), "array"),
        "field_byline" => new xmlrpcval(array(new xmlrpcval(array("value" => new xmlrpcval($node["byline"])), "struct")), "array"),
        "field_section" => new xmlrpcval(array(new xmlrpcval(array("value" => new xmlrpcval($node["section"])), "struct")), "array"),
        "field_category" => new xmlrpcval(array(new xmlrpcval(array("value" => new xmlrpcval($node["category"])), "struct")), "array")
      ),
      "struct"
    );
    
    $m = new xmlrpcmsg("node.save",
      array(
        new xmlrpcval($sessid),
        $edit
      )
    );
    
    $r = &$c->send($m);
    if(!$r->faultCode()){
      $nid = $r->value();
      return $nid;
    }else{
      print ("An error occurred on node.save: ".$r->faultString()."\n");
      $nid = 0;
      return $nid;
    }
  }
?>

Help improve this page

Page status: Not set

You can: