Index: subversion/clients/cmdline/main.c
===================================================================
--- subversion/clients/cmdline/main.c	(revision 14784)
+++ subversion/clients/cmdline/main.c	(working copy)
@@ -359,8 +359,8 @@
        "\n"
        "  Print information about each TARGET (default: '.')\n"
        "  TARGET may be either a working-copy path or URL.\n"),
-    {'r', 'R', svn_cl__targets_opt, SVN_CL__AUTH_OPTIONS, 
-     svn_cl__config_dir_opt} },
+    {'r', 'R', svn_cl__targets_opt, svn_cl__incremental_opt, svn_cl__xml_opt,
+     SVN_CL__AUTH_OPTIONS, svn_cl__config_dir_opt} },
  
   { "list", svn_cl__ls, {"ls"},
     N_("List directory entries in the repository.\n"
Index: subversion/clients/cmdline/dtd/info.dtd
===================================================================
--- subversion/clients/cmdline/dtd/info.dtd	(revision 0)
+++ subversion/clients/cmdline/dtd/info.dtd	(revision 0)
@@ -0,0 +1,54 @@
+<!-- XML DTD for Subversion command-line client output. -->
+
+<!-- For "svn info" -->
+<!ELEMENT info (target*)>
+
+<!ELEMENT target (entry*)>
+<!-- path: target supplied in cmdline -->
+<!ATTLIST target 
+  path CDATA #REQUIRED
+>
+
+<!ELEMENT entry (url?, revision, repository?, wc-info?, last-changed, conflict?, lock?)>
+<!-- path: local path -->
+<!-- type: path type -->
+<!ATTLIST entry
+  path CDATA #REQUIRED
+  type (file | directory | none | unknown) "unknown"
+>
+<!ELEMENT url (#PCDATA)> <!-- repository url -->
+<!ELEMENT revision (#PCDATA)> <!-- revision number of wc or repos path/url-->
+   
+<!ELEMENT repository (root?, uuid)>
+<!ELEMENT root (#PCDATA)> <!-- root: path type -->
+<!ELEMENT uuid (#PCDATA)> <!-- uuid: repository uuid -->
+
+<!ELEMENT wc-info (schedule?, copy-from-url?, copy-from-rev?, checksum?)>
+<!-- schedule: applies only for wc -->
+<!ELEMENT schedule (#PCDATA | normal | add | delete | replace | none)*>
+<!ELEMENT copy-from-url (#PCDATA)> 
+<!ELEMENT copy-from-rev (#PCDATA)>
+<!ELEMENT checksum (#PCDATA)>
+
+<!ELEMENT last-changed (author, last-rev, date, text-updated?, prop-updated?)>
+<!ELEMENT author (#PCDATA)> <!-- last changed author -->
+<!ELEMENT last-rev (#PCDATA)> <!-- last changed revision -->
+<!ELEMENT date (#PCDATA)> <!-- last changed date in iso format -->
+<!ELEMENT text-updated (#PCDATA)> <!-- text last updated -->
+<!ELEMENT prop-updated (#PCDATA)> <!-- properties last updated -->
+
+<!ELEMENT conflict (prev-base-file, prev-wc-file, cur-base-file, prop-file)>
+<!ELEMENT prev-base-file (#PCDATA)> <!-- previous base file -->
+<!ELEMENT prev-wc-file (#PCDATA)> <!-- previous wc file -->
+<!ELEMENT cur-base-file (#PCDATA)> <!-- current base file -->
+<!ELEMENT prop-file (#PCDATA)> <!-- current properties file -->
+
+
+<!ELEMENT lock (token, owner, created, expires?, comment?)>
+<!ELEMENT token (#PCDATA)>  <!-- lock token -->
+<!ELEMENT owner (#PCDATA)>  <!-- lock owner -->
+<!ELEMENT created (#PCDATA)>  <!-- lock created: date & time in iso format -->
+<!ELEMENT expires (#PCDATA)>  <!-- lock expires: date & time in iso format -->
+<!ELEMENT comment (#PCDATA)>  <!-- lock comment -->
+<!ATTLIST comment
+ lines CDATA #REQUIRED> 
Index: subversion/clients/cmdline/info-cmd.c
===================================================================
--- subversion/clients/cmdline/info-cmd.c	(revision 14784)
+++ subversion/clients/cmdline/info-cmd.c	(working copy)
@@ -28,6 +28,7 @@
 #include "svn_error.h"
 #include "svn_path.h"
 #include "svn_time.h"
+#include "svn_xml.h"
 #include "cl.h"
 
 #include "svn_private_config.h"
@@ -47,8 +48,372 @@
   return SVN_NO_ERROR;
 }
 
+/* Prints XML header */
+static svn_error_t *
+print_header_xml (apr_pool_t *pool)
+{
+  svn_stringbuf_t *sb = svn_stringbuf_create ("", pool);
+  /* <?xml version="1.0" encoding="utf-8"?> */
+  svn_xml_make_header (&sb, pool);
 
+  /* "<status>" */
+  svn_xml_make_open_tag (&sb, pool, svn_xml_normal, "info", NULL);
+
+  return svn_cl__error_checked_fputs (sb->data, stdout);
+}
+
+
+/* Prints XML target */
 static svn_error_t *
+print_target_xml (apr_pool_t *pool, const char *target,
+                  svn_boolean_t to_open)
+{
+  svn_stringbuf_t *sb = svn_stringbuf_create ("", pool);
+
+  if (to_open)
+    /* "<target ...>" */
+    svn_xml_make_open_tag (&sb, pool, svn_xml_normal, "target",
+                          "path", target, NULL);
+  else
+    /* "</target>" */
+    svn_xml_make_close_tag (&sb, pool, "target");
+
+  return svn_cl__error_checked_fputs (sb->data, stdout);
+}
+
+
+/* Prints XML footer */
+static svn_error_t *
+print_footer_xml (apr_pool_t *pool)
+{
+  svn_stringbuf_t *sb = svn_stringbuf_create ("", pool);
+  /* "</status>" */
+  svn_xml_make_close_tag (&sb, pool, "info");
+  return svn_cl__error_checked_fputs (sb->data, stdout);
+}
+
+
+/* prints svn info in xml mode to standard out */
+static svn_error_t *
+print_info_xml (const char *target,
+                const svn_info_t *info,
+                apr_pool_t *pool)
+{
+  const char *str_kind;
+  svn_stringbuf_t *sb = svn_stringbuf_create ("", pool);
+
+  switch (info->kind)
+    {
+    case svn_node_file:
+      str_kind = "file";
+      break;
+
+    case svn_node_dir:
+      str_kind = "directory";
+      break;
+
+    case svn_node_none:
+      str_kind = "none";
+      break;
+
+    case svn_node_unknown:
+    default:
+      str_kind = "unknown";
+      break;
+    }
+  /* "<entry ...>" */
+  svn_xml_make_open_tag (&sb, pool, svn_xml_normal, "entry",
+                         "path", svn_path_local_style (target, pool),
+                         "type", str_kind,
+                         NULL);
+
+  if (info->URL) 
+    {
+      /* "<url> xx </url>" */
+      svn_xml_make_open_tag (&sb, pool, svn_xml_protect_pcdata, "url", NULL);
+      svn_xml_escape_cdata_cstring (&sb, info->URL, pool);
+      svn_xml_make_close_tag (&sb, pool, "url");
+    }
+
+  if (SVN_IS_VALID_REVNUM (info->rev))
+    {
+       /* "<revision> xx </revision>" */
+       svn_xml_make_open_tag (&sb, pool, svn_xml_protect_pcdata,
+                              "revision", NULL);
+       svn_xml_escape_cdata_cstring (&sb, apr_psprintf (pool,
+                                     "%" APR_OFF_T_FMT, info->rev), pool);
+       svn_xml_make_close_tag (&sb, pool, "revision");
+    }
+
+  if (info->repos_root_URL || info->repos_UUID)
+    {
+      /* "<repository>" */
+      svn_xml_make_open_tag (&sb, pool, svn_xml_normal, "repository", NULL);
+
+      if (info->repos_root_URL)
+        {
+          /* "<root> xx </root>" */
+          svn_xml_make_open_tag (&sb, pool, svn_xml_protect_pcdata,
+                                 "root", NULL);
+          svn_xml_escape_cdata_cstring (&sb, info->repos_root_URL, pool);
+          svn_xml_make_close_tag (&sb, pool, "root");
+        }
+
+      if (info->repos_UUID)
+        {
+          /* "<uuid> xx </uuid>" */
+          svn_xml_make_open_tag (&sb, pool, svn_xml_protect_pcdata,
+                                 "uuid", NULL);
+          svn_xml_escape_cdata_cstring (&sb, info->repos_UUID, pool);
+          svn_xml_make_close_tag (&sb, pool, "uuid");
+        }
+
+      /* "</repository>" */
+      svn_xml_make_close_tag (&sb, pool, "repository");
+    }
+
+  if (info->has_wc_info)
+    {
+      /* "<wc-info>" */
+      svn_xml_make_open_tag (&sb, pool, svn_xml_normal, "wc-info", NULL);
+
+      /* "<schedule>" */
+      svn_xml_make_open_tag (&sb, pool, svn_xml_protect_pcdata,
+                            "schedule", NULL);
+      switch (info->schedule)
+        {
+        case svn_wc_schedule_normal:
+          svn_xml_escape_cdata_cstring (&sb, "normal", pool);
+          break;
+
+        case svn_wc_schedule_add:
+          svn_xml_escape_cdata_cstring (&sb, "add", pool);
+          break;
+
+        case svn_wc_schedule_delete:
+          svn_xml_escape_cdata_cstring (&sb, "delete", pool);
+          break;
+
+        case svn_wc_schedule_replace:
+          svn_xml_escape_cdata_cstring (&sb, "replace", pool);
+          break;
+
+        default:
+          break;
+        }
+      /* "</schedule>" */
+      svn_xml_make_close_tag (&sb, pool, "schedule");
+
+      if (info->copyfrom_url)
+        {
+          /* "<copy-from-url> xx </copy-from-url>" */
+          svn_xml_make_open_tag (&sb, pool, svn_xml_protect_pcdata,
+                                 "copy-from-url", NULL);
+          svn_xml_escape_cdata_cstring (&sb, info->copyfrom_url, pool);
+          svn_xml_make_close_tag (&sb, pool, "copy-from-url");
+        }
+
+      if (SVN_IS_VALID_REVNUM (info->copyfrom_rev))
+        {
+          /* "<copied-from-rev> xx </copied-from-rev>" */
+          svn_xml_make_open_tag (&sb, pool, svn_xml_protect_pcdata,
+                                 "copied-from-rev", NULL);
+          svn_xml_escape_cdata_cstring (&sb, apr_psprintf (pool,
+                                         "%" APR_OFF_T_FMT,
+                                         info->copyfrom_rev), pool);
+          svn_xml_make_close_tag (&sb, pool, "copied-from-rev");
+        }
+
+      if (info->checksum)
+        {
+          /* "<checksum> xx </checksum>" */
+          svn_xml_make_open_tag (&sb, pool, svn_xml_protect_pcdata,
+                                 "checksum", NULL);
+          svn_xml_escape_cdata_cstring (&sb, info->checksum, pool);
+          svn_xml_make_close_tag (&sb, pool, "checksum");
+        }
+
+      /* "</wc-info>" */
+      svn_xml_make_close_tag (&sb, pool, "wc-info");
+    }
+
+  /* "<last-changed>" */
+  svn_xml_make_open_tag (&sb, pool, svn_xml_normal, "last-changed", NULL);
+
+  if (info->last_changed_author)
+    {
+      /* "<author> xx </author>" */
+      svn_xml_make_open_tag (&sb, pool, svn_xml_protect_pcdata,
+                             "author", NULL);
+      svn_xml_escape_cdata_cstring (&sb, info->last_changed_author, pool);
+      svn_xml_make_close_tag (&sb, pool, "author");
+    }
+
+  if (SVN_IS_VALID_REVNUM (info->last_changed_rev))
+    {
+      /* "<last-rev> xx </last-rev>" */
+      svn_xml_make_open_tag (&sb, pool, svn_xml_protect_pcdata,
+                             "last-rev", NULL);
+      svn_xml_escape_cdata_cstring (&sb, apr_psprintf (pool,
+                                     "%" APR_OFF_T_FMT,
+                                     info->last_changed_rev), pool);
+      svn_xml_make_close_tag (&sb, pool, "last-rev");
+    }
+
+  if (info->last_changed_date)
+    {
+      /* "<date> xx </date>" */
+      svn_xml_make_open_tag (&sb, pool, svn_xml_protect_pcdata,
+                             "date", NULL);
+      svn_xml_escape_cdata_cstring (&sb, svn_time_to_cstring
+                                    (info->last_changed_date, pool), pool);
+      svn_xml_make_close_tag (&sb, pool, "date");
+    }
+
+  if (info->has_wc_info)
+    {
+      if (info->text_time)
+        {
+          /* "<text-updated> xx </text-updated>" */
+          svn_xml_make_open_tag (&sb, pool, svn_xml_protect_pcdata,
+                                 "text-updated", NULL);
+          svn_xml_escape_cdata_cstring (&sb, svn_time_to_cstring
+                                        (info->text_time, pool), pool);
+          svn_xml_make_close_tag (&sb, pool, "text-updated");
+        }
+
+      if (info->prop_time)
+        {
+          /* "<prop-updated> xx </prop-updated>" */
+          svn_xml_make_open_tag (&sb, pool, svn_xml_protect_pcdata,
+                                 "prop-updated", NULL);
+          svn_xml_escape_cdata_cstring (&sb, svn_time_to_cstring
+                                        (info->prop_time, pool), pool);
+          svn_xml_make_close_tag (&sb, pool, "prop-updated");
+        }
+    }
+
+  /* "</last-changed>" */
+  svn_xml_make_close_tag (&sb, pool, "last-changed");
+
+
+  if (info->conflict_old || info->conflict_wrk
+      || info->conflict_new || info->prejfile )
+    {
+      /* "<conflict>" */
+      svn_xml_make_open_tag (&sb, pool, svn_xml_normal, "conflict", NULL);
+
+      if (info->conflict_old)
+        {
+          /* "<prev-basefile> xx </prev-basefile>" */
+          svn_xml_make_open_tag (&sb, pool, svn_xml_protect_pcdata,
+                                 "prev-basefile", NULL);
+          svn_xml_escape_cdata_cstring (&sb, info->conflict_old, pool);
+          svn_xml_make_close_tag (&sb, pool, "prev-basefile");
+       }
+
+      if (info->conflict_wrk)
+        {
+          /* "<prev-wrkfile> xx </prev-wrkfile>" */
+          svn_xml_make_open_tag (&sb, pool, svn_xml_protect_pcdata,
+                                 "prev-wrkfile", NULL);
+          svn_xml_escape_cdata_cstring (&sb, info->conflict_wrk, pool);
+          svn_xml_make_close_tag (&sb, pool, "prev-wrkfile");
+       }
+
+      if (info->conflict_new)
+        {
+          /* "<cur-basefile> xx </cur-basefile>" */
+          svn_xml_make_open_tag (&sb, pool, svn_xml_protect_pcdata,
+                                 "cur-basefile", NULL);
+          svn_xml_escape_cdata_cstring (&sb, info->conflict_new, pool);
+          svn_xml_make_close_tag (&sb, pool, "cur-basefile");
+       }
+
+      if (info->prejfile)
+        {
+          /* "<prop-file> xx </prop-file>" */
+          svn_xml_make_open_tag (&sb, pool, svn_xml_protect_pcdata,
+                                 "prop-file", NULL);
+          svn_xml_escape_cdata_cstring (&sb, info->prejfile, pool);
+          svn_xml_make_close_tag (&sb, pool, "prop-file");
+        }
+
+      /* "</conflict>" */
+      svn_xml_make_close_tag (&sb, pool, "conflict");
+    }
+
+  if (info->lock)
+    {
+      /* "<lock>" */
+      svn_xml_make_open_tag (&sb, pool, svn_xml_normal, "lock", NULL);
+
+      if (info->lock->token)
+        {
+          /* "<token> xx </token>" */
+          svn_xml_make_open_tag (&sb, pool, svn_xml_protect_pcdata,
+                                 "token", NULL);
+          svn_xml_escape_cdata_cstring (&sb, info->lock->token, pool);
+          svn_xml_make_close_tag (&sb, pool, "token");
+       }
+
+      if (info->lock->owner)
+        {
+          /* "<owner> xx </owner>" */
+          svn_xml_make_open_tag (&sb, pool, svn_xml_protect_pcdata,
+                                 "owner", NULL);
+          svn_xml_escape_cdata_cstring (&sb, info->lock->owner, pool);
+          svn_xml_make_close_tag (&sb, pool, "owner");
+       }
+
+      if (info->lock->creation_date)
+        {
+          /* "<created> xx </created>" */
+          svn_xml_make_open_tag (&sb, pool, svn_xml_protect_pcdata,
+                                 "created", NULL);
+          svn_xml_escape_cdata_cstring (&sb, svn_time_to_cstring
+                                        (info->lock->creation_date, pool),
+                                        pool);
+          svn_xml_make_close_tag (&sb, pool, "created");
+       }
+
+      if (info->lock->expiration_date)
+        {
+          /* "<expires> xx </expires>" */
+          svn_xml_make_open_tag (&sb, pool, svn_xml_protect_pcdata,
+                                 "expires", NULL);
+          svn_xml_escape_cdata_cstring (&sb, svn_time_to_cstring
+                                        (info->lock->expiration_date, pool),
+                                        pool);
+          svn_xml_make_close_tag (&sb, pool, "expires");
+       }
+
+      if (info->lock->comment)
+        {
+          /* "<comment ...> xxxx </comment>" */
+          int comment_lines;
+          /* NOTE: The stdio will handle newline translation. */
+          comment_lines = svn_cstring_count_newlines (info->lock->comment) + 1;
+          svn_xml_make_open_tag (&sb, pool, svn_xml_normal, "comment",
+                                 "lines", apr_psprintf (pool, "%d",
+                                  comment_lines), NULL);
+
+          svn_xml_escape_cdata_cstring (&sb, info->lock->comment, pool);
+          svn_xml_make_close_tag (&sb, pool, "comment");
+        }
+
+      /* "</lock>" */
+      svn_xml_make_close_tag (&sb, pool, "lock");
+        }
+
+  /* "</entry>" */
+  svn_xml_make_close_tag (&sb, pool, "entry");
+
+  return svn_cl__error_checked_fputs (sb->data, stdout);
+}
+
+
+static svn_error_t *
 print_info (const char *target,
             const svn_info_t *info,
             apr_pool_t *pool)
@@ -225,7 +590,10 @@
                const svn_info_t *info,
                apr_pool_t *pool)
 {
-  return print_info (path, info, pool);
+  if ((((svn_cl__cmd_baton_t *) baton)->opt_state)->xml) 
+    return print_info_xml (path, info, pool);
+  else
+    return print_info (path, info, pool);
 }
 
 
@@ -249,6 +617,23 @@
 
   /* Add "." if user passed 0 arguments. */
   svn_opt_push_implicit_dot_target (targets, pool);
+
+  if (opt_state->xml)
+    {
+      /* If output is not incremental, output the XML header and wrap
+         everything in a top-level element. This makes the output in
+         its entirety a well-formed XML document. */
+      if (! opt_state->incremental)
+        SVN_ERR (print_header_xml (pool));
+
+    }
+  else
+    {
+      if (opt_state->incremental)
+        return svn_error_create (SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                                 _("'incremental' option only valid in XML "
+                                   "mode"));
+    }
   
   for (i = 0; i < targets->nelts; i++)
     {
@@ -266,26 +651,34 @@
           && (peg_revision.kind == svn_opt_revision_unspecified))
         peg_revision.kind = svn_opt_revision_head;
 
+      if (opt_state->xml)
+         print_target_xml (pool, target, TRUE);
+
       err = svn_client_info (truepath,
                              &peg_revision, &(opt_state->start_revision),
-                             info_receiver, NULL,
+                             info_receiver, baton,
                              opt_state->recursive, ctx, subpool);
 
+       if (opt_state->xml)
+         print_target_xml (pool, target, FALSE);
+         
       /* If one of the targets is a non-existent URL or wc-entry,
          don't bail out.  Just warn and move on to the next target. */
       if (err && err->apr_err == SVN_ERR_UNVERSIONED_RESOURCE)
         {
           svn_error_clear (err);
-          SVN_ERR (svn_cmdline_printf
-                   (subpool, _("%s:  (Not a versioned resource)\n\n"),
+          SVN_ERR (svn_cmdline_fprintf
+                   (stderr, subpool,
+                    _("%s:  (Not a versioned resource)\n\n"),
                     svn_path_local_style (target, pool)));
           continue;
         }
       else if (err && err->apr_err == SVN_ERR_RA_ILLEGAL_URL)
         {
           svn_error_clear (err);
-          SVN_ERR (svn_cmdline_printf
-                   (subpool, _("%s:  (Not a valid URL)\n\n"),
+          SVN_ERR (svn_cmdline_fprintf
+                   (stderr, subpool,
+                    _("%s:  (Not a valid URL)\n\n"),
                     svn_path_local_style (target, pool)));
           continue;
         }
@@ -295,5 +688,8 @@
     }
   svn_pool_destroy (subpool);
 
+  if (opt_state->xml && (! opt_state->incremental))
+    err = print_footer_xml (pool);
+
   return SVN_NO_ERROR;
 }
Index: tools/client-side/bash_completion
===================================================================
--- tools/client-side/bash_completion	(revision 14784)
+++ tools/client-side/bash_completion	(working copy)
@@ -99,7 +99,8 @@
 		         --editor-cmd $pOpts"
 		;; 
 	info)
-		cmdOpts="$rOpts --targets -R --recursive"
+		cmdOpts="$rOpts --targets -R --recursive \
+                         --incremental --xml"
 		;;
 	list|ls)
 		cmdOpts="$rOpts -v --verbose -R --recursive $pOpts \
