Index: release/project-release-create-history.php
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/project/release/project-release-create-history.php,v
retrieving revision 1.29
diff -u -p -r1.29 project-release-create-history.php
--- release/project-release-create-history.php	17 Jan 2010 00:00:11 -0000	1.29
+++ release/project-release-create-history.php	16 Feb 2010 06:06:38 -0000
@@ -15,6 +15,11 @@
  *
  */
 
+define('XML_NS', 'http://www.w3.org/2000/xmlns/');
+
+// Dublin core namespace according to http://dublincore.org/documents/dcmi-namespace/
+define('XML_DC_NS', 'http://purl.org/dc/elements/1.1/');
+
 // ------------------------------------------------------------
 // Required customization
 // ------------------------------------------------------------
@@ -215,14 +220,20 @@ function project_release_history_generat
     }
   }
 
-  $xml = '<title>'. check_plain($project->title) ."</title>\n";
-  $xml .= '<short_name>'. check_plain($project->uri) ."</short_name>\n";
-  $xml .= '<dc:creator>'. check_plain($project->username) ."</dc:creator>\n";
-  $xml .= '<api_version>'. check_plain($api_version) ."</api_version>\n";
+  $dom = new DomDocument('1.0', 'utf-8');
+  $dom->formatOutput = TRUE;
+
+  $eproject = $dom->appendChild($dom->createElement('project'));
+  $eproject->setAttributeNS(XML_NS, 'xmlns:dc', XML_DC_NS);
+  $eproject->appendChild($dom->createElement('title', $node->title));
+  $eproject->appendChild($dom->createElement('short_name', $node->uri));
+  $eproject->appendChild($dom->createElementNS(XML_DC_NS, 'dc:creator', $project->username));
+  $eproject->appendChild($dom->createElement('api_version', $api_version));
+
   if (!$project->status) {
     // If it's not published, we can skip the rest of this and bail.
-    $xml .= "<project_status>unpublished</project_status>\n";
-    project_release_history_write_xml($xml, $project, $api_version);
+    $eproject->appendChild($dom->createElement('project_status', 'unpublished'));
+    project_release_history_write_xml($dom, $project, $api_version);
     return;
   }
 
@@ -240,31 +251,29 @@ function project_release_history_generat
       }
     }
     if (isset($recommended_major)) {
-      $xml .= '<recommended_major>'. $recommended_major ."</recommended_major>\n";
+      $eproject->appendChild($dom->createElement('recommended_major', $recommended_major));
     }
     if (empty($supported_majors)) {
       $project_status = 'unsupported';
     }
     else {
-      $xml .= '<supported_majors>'. implode(',', $supported_majors) ."</supported_majors>\n";
+      $eproject->appendChild($dom->createElement('supported_majors', implode(',', $supported_majors)));
       // To avoid confusing existing clients, include <default_major>, too.
-      $xml .= '<default_major>'. min($supported_majors) ."</default_major>\n";
+      $eproject->appendChild($dom->createElement('default_major', min($supported_majors)));
     }
   }
 
-  $xml .= '<project_status>'. $project_status ."</project_status>\n";
-  $xml .= '<link>'. prch_url("node/$project->nid") ."</link>\n";
+  $eproject->appendChild($dom->createElement('project_status', $project_status));
+  $eproject->appendChild($dom->createElement('link', prch_url("node/$project->nid")));
 
   // To prevent the update(_status) module from having problems parsing the XML,
   // the terms need to be at the end of the information for the project.
   $term_query = db_query("SELECT v.name AS vocab_name, v.vid, td.name AS term_name, td.tid FROM {term_node} tn INNER JOIN {term_data} td ON tn.tid = td.tid INNER JOIN {vocabulary} v ON td.vid = v.vid WHERE tn.vid = %d", $project->vid);
-  $xml_terms = '';
+  $xml_terms = $eproject->appendChild($dom->createElement('terms'));
   while ($term = db_fetch_object($term_query)) {
-    $xml_terms .= '   <term><name>'. check_plain($term->vocab_name) .'</name>';
-    $xml_terms .= '<value>'. check_plain($term->term_name) ."</value></term>\n";
-  }
-  if (!empty($xml_terms)) {
-    $xml .= "  <terms>\n". $xml_terms ."  </terms>\n";
+    $xml_term = $xml_terms->appendChild($dom->createElement('term'));
+    $xml_term->appendChild($dom->createElement('name', $term->vocab_name));
+    $xml_term->appendChild($dom->createElement('value', $term->term_name));
   }
 
   // Now, build the query for all the releases for this project and term.
@@ -320,62 +329,58 @@ function project_release_history_generat
 
   if (empty($releases)) {
     // Nothing more to include for this project, wrap up and return.
-    project_release_history_write_xml($xml, $project, $api_version);
+    project_release_history_write_xml($dom, $project, $api_version);
     return;
   }
 
   // Sort the releases based on our custom sorting function.
   usort($releases, "_release_sort");
 
-  $xml .= "<releases>\n";
+  $ereleases = $eproject->appendChild($dom->createElement('releases'));
   foreach ($releases as $release) {
-    $xml .= " <release>\n";
-    $xml .= '  <name>'. check_plain($release->title) ."</name>\n";
-    $xml .= '  <version>'. check_plain($release->version) ."</version>\n";
-    if (!empty($release->tag) && $tag = check_plain($release->tag)) {
-      $xml .= '  <tag>'. $tag ."</tag>\n";
+    $erelease = $ereleases->appendChild($dom->createElement('release'));
+    $erelease->appendChild($dom->createElement('name', $release->title));
+    $erelease->appendChild($dom->createElement('version', $release->version));
+    if (!empty($release->tag)) {
+      $erelease->appendChild($dom->createElement('tag', $release->tag));
     }
     foreach (array('major', 'minor', 'patch', 'extra') as $type) {
       $vers_type = "version_$type";
       if (isset($release->$vers_type)) {
-        $xml .= "  <$vers_type>". check_plain($release->$vers_type) ."</$vers_type>\n";
+        $erelease->appendChild($dom->createElement($vers_type, $release->$vers_type));
       }
     }
     if ($release->status) {
       // Published, so we should include the links.
-      $xml .= "  <status>published</status>\n";
-      $xml .= '  <release_link>'. prch_url("node/$release->nid") ."</release_link>\n";
+      $erelease->appendChild($dom->createElement('status', 'published'));
+      $erelease->appendChild($dom->createElement('release_link', prch_url("node/$release->nid")));
       if (!empty($release->filepath)) {
         $download_link = theme('project_release_download_link', $release->filepath, NULL, TRUE);
-        $xml .= '  <download_link>'. $download_link['href'] ."</download_link>\n";
+        $erelease->appendChild($dom->createElement('download_link', $download_link['href']));
       }
     }
     else {
-      $xml .= "  <status>unpublished</status>\n";
+      $erelease->appendChild($dom->createElement('status', 'published'));
     }
     // We want to include the rest of these regardless of the status.
     if (!empty($release->timestamp)) {
-      $xml .= '  <date>'. check_plain($release->timestamp) ."</date>\n";
+      $erelease->appendChild($dom->createElement('date', $release->timestamp));
     }
     if (!empty($release->filehash)) {
-      $xml .= '  <mdhash>'. check_plain($release->filehash) ."</mdhash>\n";
+      $erelease->appendChild($dom->createElement('mdhash', $release->filehash));
     }
     if (isset($release->filesize)) {
-      $xml .= '  <filesize>'. check_plain($release->filesize) ."</filesize>\n";
+      $erelease->appendChild($dom->createElement('filesize', $release->filesize));
     }
     $term_query = db_query("SELECT v.name AS vocab_name, v.vid, td.name AS term_name, td.tid FROM {term_node} tn INNER JOIN {term_data} td ON tn.tid = td.tid INNER JOIN {vocabulary} v ON td.vid = v.vid WHERE tn.vid = %d AND v.vid != %d", $release->vid, $api_vid);
-    $xml_terms = '';
+    $xml_terms = $erelease->appendChild($dom->createElement('terms'));
     while ($term = db_fetch_object($term_query)) {
-      $xml_terms .= '   <term><name>'. check_plain($term->vocab_name) .'</name>';
-      $xml_terms .= '<value>'. check_plain($term->term_name) ."</value></term>\n";
-    }
-    if (!empty($xml_terms)) {
-      $xml .= "  <terms>\n". $xml_terms ."  </terms>\n";
+      $xml_term = $xml_terms->appendChild($dom->createElement('term'));
+      $xml_term->appendChild($dom->createElement('name', $term->vocab_name));
+      $xml_term->appendChild($dom->createElement('value', $term->term_name));
     }
-    $xml .= " </release>\n";
   }
-  $xml .= "</releases>\n";
-  project_release_history_write_xml($xml, $project, $api_version);
+  project_release_history_write_xml($dom, $project, $api_version);
 }
 
 
@@ -383,16 +388,13 @@ function project_release_history_generat
  * Write out the XML history for a given project and version to a file.
  *
  * @param $xml
- *   String containing the XML representation of the history.
+ *   DomDocument representing the history.
  * @param $project
  *   An object containing (at least) the title and uri of project.
  * @param $api_version
  *   The API compatibility version the history is for.
  */
-function project_release_history_write_xml($xml, $project = NULL, $api_version = NULL) {
-
-  // Dublin core namespace according to http://dublincore.org/documents/dcmi-namespace/
-  $dc_namespace = 'xmlns:dc="http://purl.org/dc/elements/1.1/"';
+function project_release_history_write_xml($dom, $project = NULL, $api_version = NULL) {
   if (!isset($project)) {
     // We are outputting a global project list.
     $project_dir = HISTORY_ROOT .'/project-list';
@@ -412,8 +414,6 @@ function project_release_history_write_x
         'args' => array('@old' => $tmp_filename, '@new' => $filename),
       ),
     );
-    $full_xml = '<?xml version="1.0" encoding="utf-8"?>' . "\n";
-    $full_xml .= '<projects '. $dc_namespace .">\n" . $xml . "</projects>\n";
   }
   else {
     // Setup the filenames we'll be using.  Normally, we'd have to be
@@ -442,8 +442,6 @@ function project_release_history_write_x
         'args' => array('@old' => $tmp_filename, '@new' => $filename, '%project' => $project->title),
       ),
     );
-    $full_xml = '<?xml version="1.0" encoding="utf-8"?>' . "\n";
-    $full_xml .= '<project '. $dc_namespace .">\n" . $xml . "</project>\n";
   }
 
   // Make sure we've got the right project-specific subdirectory.
@@ -461,6 +459,8 @@ function project_release_history_write_x
     wd_err(array('message' => "ERROR: fopen(@file, 'xb') failed", 'args' => array('@file' => $tmp_filename)));
     return FALSE;
   }
+
+  $full_xml = $dom->saveXML();
   if (!fwrite($hist_fd, $full_xml)) {
     wd_err(array('message' => "ERROR: fwrite(@file) failed" . '<pre>' . check_plain($full_xml), 'args' => array('@file' => $tmp_filename)));
     return FALSE;
@@ -484,46 +484,46 @@ function project_list_generate() {
   
   $query = db_query("SELECT n.title, n.nid, n.vid, n.status, p.uri, u.name AS username FROM {node} n INNER JOIN {project_projects} p ON n.nid = p.nid INNER JOIN {users} u ON n.uid = u.uid");
 
-  $xml = '';
+  $has_projects = FALSE;
+  $dom = new DomDocument('1.0', 'utf-8');
+  $dom->formatOutput = TRUE;
+
+  $eprojects = $dom->appendChild($dom->createElement('projects'));
+  $eprojects->setAttributeNS(XML_NS, 'xmlns:dc', XML_DC_NS);
   while ($project = db_fetch_object($query)) {
-    $xml .= " <project>\n";
-    $xml .= '  <title>'. check_plain($project->title) ."</title>\n";
-    $xml .= '  <short_name>'. check_plain($project->uri) ."</short_name>\n";
-    $xml .= '  <link>'. prch_url("node/$project->nid") ."</link>\n";
-    $xml .= '  <dc:creator>'. check_plain($project->username). "</dc:creator>\n";
+    $has_projects = TRUE;
+    $eproject = $eprojects->appendChild($dom->createElement('project'));
+    $eproject->appendChild($dom->createElement('title', $project->title));
+    $eproject->appendChild($dom->createElement('short_name', $project->title));
+    $eproject->appendChild($dom->createElement('link', $project->title));
+    $eproject->appendChild($dom->createElementNS(XML_DC_NS, 'dc:creator', $project->username));
+
     $term_query = db_query("SELECT v.name AS vocab_name, v.vid, td.name AS term_name, td.tid FROM {term_node} tn INNER JOIN {term_data} td ON tn.tid = td.tid INNER JOIN {vocabulary} v ON td.vid = v.vid WHERE tn.vid = %d", $project->vid);
-    $xml_terms = '';
+    $xml_terms = $eproject->appendChild($dom->createElement('terms'));
     while ($term = db_fetch_object($term_query)) {
-      $xml_terms .= '   <term><name>'. check_plain($term->vocab_name) .'</name>';
-      $xml_terms .= '<value>'. check_plain($term->term_name) ."</value></term>\n";
-    }
-    if (!empty($xml_terms)) {
-      $xml .= "  <terms>\n". $xml_terms ."  </terms>\n";
+      $xml_term = $xml_terms->appendChild($dom->createElement('term'));
+      $xml_term->appendChild($dom->createElement('name', $term->vocab_name));
+      $xml_term->appendChild($dom->createElement('value', $term->term_name));
     }
     if (!$project->status) {
       // If it's not published, we can skip the rest for this project.
-      $xml .= "  <project_status>unpublished</project_status>\n";
+      $eproject->appendChild($dom->createElement('status', 'unpublished'));
     }
     else {
-      $xml .= "  <project_status>published</project_status>\n";
+      $eproject->appendChild($dom->createElement('status', 'published'));
       // Include a list of API terms if available.
       $term_query = db_query("SELECT DISTINCT(td.tid), td.name AS term_name FROM {project_release_nodes} prn INNER JOIN {term_data} td ON prn.version_api_tid = td.tid WHERE prn.pid = %d AND td.vid = %d ORDER BY td.weight ASC", $project->nid, $api_vid);
-      $xml_api_terms = '';
+      $xml_api_terms = $eproject->appendChild($dom->createElement('api_versions'));
       while ($api_term = db_fetch_object($term_query)) {
-        $xml_api_terms .= '   <api_version>'. check_plain($api_term->term_name) ."</api_version>\n";
-      }      
-      if (!empty($xml_api_terms)) {
-        $xml .= "  <api_versions>\n". $xml_api_terms ."  </api_versions>\n";
+        $xml_api_terms->appendChild($dom->createElement('api_version', $api_term->term_name));
       }
     }
-    
-    $xml .= " </project>\n";
   }
-  if (empty($xml)) {
+  if (!$has_projects) {
     wd_err(array('message' => 'No projects found on this server.'));
     return FALSE;
   }
-  project_release_history_write_xml($xml);
+  project_release_history_write_xml($dom);
 }
 
 // ------------------------------------------------------------
