Logo Search packages:      
Sourcecode: hnb version File versions  Download package

file_xml.c

/*
 * file_ascii.c -- generic xml import/export filters for hnb
 *
 * Copyright (C) 2001-2003 Øyvind Kolås <pippin@users.sourceforge.net>
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 59
 * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#if HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "xml_tok.h"

#include "cli.h"
#include "tree.h"

#include "file.h"
#include "prefs.h"
#include "query.h"
#include "util_string.h"

#define indent(count,char)    {int j;for(j=0;j<count;j++)fprintf(file,char);}

static int xml_cuddle = 0;

static char *xmlquote[]={
      "<","&lt;",
      ">","&gt;",
      "&","&amp;",
      "\"","&quot;",
      "'","&apos;",
      NULL
};

static char *xmlunquote[]={
      "&lt;","<",
      "&gt;",">",
      "&amp;","&",
      "&quot;","\"",
      "&apos;","'",
      NULL
};

/* returns the first occurence of one of the needles, or 0 (termination)
   if not found, return 0*/
static int findchar (char *haystack, char *needles)
{
      int j = 0;
      int k;

      while (haystack[j]) {
            for (k = 0; k < strlen (needles) + 1; k++)
                  if (haystack[j] == needles[k])
                        return j;
            j++;
      }
      return 0;
}

static void xml_export_nodes (FILE * file, Node *node, int level)
{
      char tag[bufsize];
      int flags;
      char *data;

      static int no_quote = 0;

      while (node) {
            int data_start = 0;

            tag[0] = 0;
            flags = node_getflags (node);
            data = fixnullstring (node_get (node, TEXT));

            indent (level, "  ");

            if (data[0] == '<') {   /* calculate start tag, if any */
                  strcpy (tag, data);
                  data_start = findchar (tag, ">") + 1;
                  tag[data_start] = 0;
                  if (data[1] == '!' || data[1] == '?') {
                        no_quote++;
                  }
            }

            if (no_quote)
                  fprintf (file, "%s%s", tag, &data[data_start]);
            else{
                  char *quoted=string_replace(&data[data_start],xmlquote);
                  fprintf (file, "%s%s", tag, quoted);
                  free(quoted);
            }

            if (data[0] == '<') {   /* calculate end tag */
                  strcpy (tag, data);
                  tag[findchar (tag, " \t>") + 1] = 0;
                  tag[findchar (tag, " \t>")] = '>';
                  tag[0] = '/';
            }

            if (node_right (node)) {
                  fprintf (file, "\n");
                  xml_export_nodes (file, node_right (node), level + 1);
                  indent (level, "  ");
                  if (data[0] == '<') {
                        if (data[1] == '!' && data[2] == '-') {
                              fprintf (file, " -->\n");
                        } else if (tag[1] != '?' && tag[1] != '!') {
                              fprintf (file, "<%s\n", tag);
                        } else {
                              fprintf (file, "\n");
                        }
                  }
            } else {
                  if (data[0] == '<' && data[strlen (data) - 2] != '/') {
                        if (data[1] == '!' && data[2] == '-') {
                              fprintf (file, " -->\n");
                        } else if (tag[1] != '?' && tag[1] != '!') {
                              fprintf (file, "<%s\n", tag);
                        } else {
                              fprintf (file, "\n");
                        }
                  } else
                        fprintf (file, "\n");
            }
            if (data[0] == '<' && (data[1] == '!' || data[1] == '?')) {
                  no_quote--;
            }

            node = node_down (node);
      }
}

static int export_xml (int argc, char **argv, void *data)
{
      Node *node = (Node *) data;
      char *filename = argc==2?argv[1]:"";
      FILE *file;

      if (!strcmp (filename, "-"))
            file = stdout;
      else
            file = fopen (filename, "w");
      if (!file) {
            cli_outfunf ("xml export, unable to open \"%s\"", filename);
            return (int) node;
      }

      xml_export_nodes (file, node, 0);

      if (file != stdout)
            fclose (file);

      cli_outfunf ("xml export, wrote data to \"%s\"", filename);


      return (int) node;
}

/* joins up tags with data if there is data as the first child
   of the tag.*/
static Node *xml_cuddle_nodes (Node *node)
{

      Node *tnode;
      char *tdata;
      char data[bufsize];

      tnode = node_root (node);

      while (tnode) {
            if (node_right (tnode)) {
                  tdata = fixnullstring (node_get (node_right (tnode), TEXT));
                  if (tdata[0] != '<') {  /* not a child tag */
                        strcpy (data, fixnullstring (node_get (tnode, TEXT)));
                        strcat (data, " ");
                        strcat (data, tdata);
                        node_set (tnode, TEXT, data);
                        node_remove (node_right (tnode));
                  }
            }
            tnode = node_recurse (tnode);
      }

      return (node);
}


static int import_xml (int argc, char **argv, void *data)
{
      Node *node = (Node *) data;
      char *filename = argc==2?argv[1]:"";
      char *rdata;
      int type;
      int level = 0;
      char nodedata[4096];
      xml_tok_state *s;
      import_state_t ist;
      int got_data = 0;

      FILE *file;

      nodedata[0] = 0;

      file = fopen (filename, "r");
      if (!file) {
            cli_outfunf ("xml import, unable to open \"%s\"", filename);
            return (int) node;
      }
      s = xml_tok_init (file);
      init_import (&ist, node);

      while (((type = xml_tok_get (s, &rdata)) != t_eof)) {
            if (type == t_error) {
                  cli_outfunf ("xml import error, parsing og '%s', line:%i %s", filename,
                                     s->line_no,rdata);
                  fclose (file);
                  return (int) node;
            }

            switch (type) {
                  case t_prolog:
                        sprintf (nodedata, "<?%s?>", rdata);
                        import_node_text (&ist, level, nodedata);
                        nodedata[0] = 0;
                        got_data = 0;
                        break;
                  case t_dtd:
                        sprintf (nodedata, "<!%s>", rdata);
                        import_node_text (&ist, level, nodedata);
                        nodedata[0] = 0;
                        got_data = 0;
                        break;
                  case t_comment:
                        sprintf (nodedata, "<!--%s-->", rdata);
                        import_node_text (&ist, level, nodedata);
                        break;
                  case t_tag:
                        if (got_data) {
                              char *unquoted=string_replace(nodedata,xmlunquote);
                              import_node_text (&ist, level, unquoted);
                              free(unquoted);
                              got_data = 0;
                              nodedata[0] = 0;
                        }
                        sprintf (nodedata, "<%s", rdata);
                        break;
                  case t_att:
                        sprintf (&nodedata[strlen (nodedata)], " %s=", rdata);
                        break;
                  case t_val:
                        if (strchr (rdata, '"')) {
                              sprintf (&nodedata[strlen (nodedata)], "'%s'", rdata);
                        } else {
                              if (strchr (rdata, '\'')) {
                                    sprintf (&nodedata[strlen (nodedata)], "\"%s\"",
                                                 rdata);
                              } else {
                                    sprintf (&nodedata[strlen (nodedata)], "\"%s\"",
                                                 rdata);
                              }
                        }
                        break;
                  case t_endtag:
                        sprintf (&nodedata[strlen (nodedata)], ">");

                        import_node_text (&ist, level, nodedata);
                        nodedata[0] = 0;
                        level++;
                        break;
                  case t_closeemptytag:
                        sprintf (&nodedata[strlen (nodedata)], "/>");

                        import_node_text (&ist, level, nodedata);
                        nodedata[0] = 0;
                        break;
                  case t_closetag:
                        if (got_data) {
                              char *unquoted=string_replace(nodedata,xmlunquote);
                              import_node_text (&ist, level, unquoted);
                              free(unquoted);
                              got_data = 0;
                              nodedata[0] = 0;
                        }
                        level--;
                        sprintf (nodedata, "</%s>", rdata);
                        nodedata[0] = 0;
                        break;
                  case t_whitespace:
                        if (got_data) {
                              strcpy (&nodedata[strlen (nodedata)], " ");
                        }
                        break;
                  case t_word:
                        strcpy (&nodedata[strlen (nodedata)], rdata);
                        got_data = 1;
                        break;
                  case t_entity:
                        got_data = 1;
                        sprintf (&nodedata[strlen (nodedata)], "&%s;", rdata);
                        break;
                  default:
                        break;
            }
      }

      if (node_getflag (node, F_temp))
            node = node_remove (node);    /* remove temporary node, if tree was empty */

      if (xml_cuddle)
            node = xml_cuddle_nodes (node);

      cli_outfunf ("xml import - imported \"%s\" %i lines", filename, s->line_no);
      xml_tok_cleanup (s);
      return (int) node;
}

/*
!init_file_xml();
*/
void init_file_xml ()
{
      cli_add_command ("export_xml", export_xml, "<filename>");
      cli_add_command ("import_xml", import_xml, "<filename>");
      cli_add_help ("export_xml",
                          "Exports the current node, it's siblings and all sublevels to 'filename' as if it was xml markup.\
(load an xml file with import_xml or hnb -x file.xml to see how it should be inside hnb.");
      cli_add_help ("import_xml",
                          "Imports 'filename' and inserts it's contents at the current level.");
      cli_add_int ("xml_cuddle", &xml_cuddle,
                         "join the data with nodes if no tags within tag");
}

Generated by  Doxygen 1.6.0   Back to index