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("/&/", "&", $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:
You can:
- Log in, click Edit, and edit this page
- Log in, click Discuss, update the Page status value, and suggest an improvement
- Log in and create a Documentation issue with your suggestion