256 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			256 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*  $Id$
 | 
						|
 | 
						|
    Part of SWI-Prolog
 | 
						|
 | 
						|
    Author:        Jan Wielemaker
 | 
						|
    E-mail:        jan@swi.psy.uva.nl
 | 
						|
    WWW:           http://www.swi-prolog.org
 | 
						|
    Copyright (C): 1985-2002, University of Amsterdam
 | 
						|
 | 
						|
    This library is free software; you can redistribute it and/or
 | 
						|
    modify it under the terms of the GNU Lesser General Public
 | 
						|
    License as published by the Free Software Foundation; either
 | 
						|
    version 2.1 of the License, or (at your option) any later version.
 | 
						|
 | 
						|
    This library 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
 | 
						|
    Lesser General Public License for more details.
 | 
						|
 | 
						|
    You should have received a copy of the GNU Lesser General Public
 | 
						|
    License along with this library; if not, write to the Free Software
 | 
						|
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
						|
*/
 | 
						|
 | 
						|
#include <stdio.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include "dtd.h"
 | 
						|
#include "parser.h"
 | 
						|
 | 
						|
#ifdef XMLNS
 | 
						|
 | 
						|
xmlns *
 | 
						|
xmlns_push(dtd_parser *p, const ichar *ns, const ichar *url)
 | 
						|
{ sgml_environment *env = p->environments;
 | 
						|
  dtd_symbol *n = (*ns ? dtd_add_symbol(p->dtd, ns) : (dtd_symbol *)NULL);
 | 
						|
  dtd_symbol *u = dtd_add_symbol(p->dtd, url); /* TBD: ochar/ichar */
 | 
						|
  xmlns *x = sgml_malloc(sizeof(*x));
 | 
						|
 | 
						|
  x->name = n;
 | 
						|
  x->url  = u;
 | 
						|
 | 
						|
  if ( env )
 | 
						|
  { if ( p->on_xmlns )
 | 
						|
      (*p->on_xmlns)(p, n, u);
 | 
						|
 | 
						|
    x->next = env->xmlns;
 | 
						|
    env->xmlns = x;
 | 
						|
  } else
 | 
						|
  { x->next = p->xmlns;
 | 
						|
    p->xmlns = x;
 | 
						|
  }
 | 
						|
 | 
						|
  return x;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void
 | 
						|
xmlns_free(xmlns *n)
 | 
						|
{ xmlns *next;
 | 
						|
 | 
						|
  for(; n; n = next)
 | 
						|
  { next = n->next;
 | 
						|
 | 
						|
    sgml_free(n);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
xmlns *
 | 
						|
xmlns_find(dtd_parser *p, dtd_symbol *ns)
 | 
						|
{ sgml_environment *env = p->environments;
 | 
						|
  xmlns *n;
 | 
						|
 | 
						|
  for(; env; env = env->parent)
 | 
						|
  { for(n=env->xmlns; n; n = n->next)
 | 
						|
    { if ( n->name == ns )
 | 
						|
	return n;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  for (n=p->xmlns; n; n = n->next)
 | 
						|
  { if ( n->name == ns )
 | 
						|
      return n;
 | 
						|
  }
 | 
						|
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static ichar *
 | 
						|
isxmlns(const ichar *s, int nschr)
 | 
						|
{ if ( s[0]=='x' && s[1]=='m' && s[2]=='l' && s[3] =='n'&& s[4]=='s' )
 | 
						|
  { if ( !s[5] )
 | 
						|
      return (ichar *)s+5;			/* implicit */
 | 
						|
    if ( s[5] == nschr )
 | 
						|
      return (ichar *)s+6;
 | 
						|
  }
 | 
						|
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void
 | 
						|
update_xmlns(dtd_parser *p, dtd_element *e, int natts, sgml_attribute *atts)
 | 
						|
{ dtd_attr_list *al;
 | 
						|
  int nschr = p->dtd->charfunc->func[CF_NS]; /* : */
 | 
						|
 | 
						|
  for(al=e->attributes; al; al=al->next)
 | 
						|
  { dtd_attr *a = al->attribute;
 | 
						|
    const ichar *name = a->name->name;
 | 
						|
 | 
						|
    if ( (name = isxmlns(name, nschr)) && /* TBD: flag when processing DTD */
 | 
						|
	 a->type == AT_CDATA &&
 | 
						|
	 (a->def == AT_FIXED || a->def == AT_DEFAULT) )
 | 
						|
      xmlns_push(p, name, a->att_def.cdata);
 | 
						|
  }
 | 
						|
 | 
						|
  for( ; natts-- > 0; atts++ )
 | 
						|
  { const ichar *name = atts->definition->name->name;
 | 
						|
 | 
						|
    if ( (name=isxmlns(name, nschr)) &&
 | 
						|
	 atts->definition->type == AT_CDATA &&
 | 
						|
	 atts->value.textW )
 | 
						|
      xmlns_push(p, name, atts->value.textW);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
						|
xmlns_resolve()
 | 
						|
    Convert a symbol as returned by the XML level-1.0 parser to its namespace
 | 
						|
    tuple {url}localname.  This function is not used internally, but provided
 | 
						|
    for use from the call-back functions of the parser.
 | 
						|
 | 
						|
    It exploits the stack of namespace-environments managed by the parser
 | 
						|
    itself (see update_xmlns())
 | 
						|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 | 
						|
 | 
						|
int
 | 
						|
xmlns_resolve_attribute(dtd_parser *p, dtd_symbol *id,
 | 
						|
			const ichar **local, const ichar **url)
 | 
						|
{ dtd *dtd = p->dtd;
 | 
						|
  int nschr = dtd->charfunc->func[CF_NS]; /* : */
 | 
						|
  ichar buf[MAXNMLEN];
 | 
						|
  ichar *o = buf;
 | 
						|
  const ichar *s;
 | 
						|
  xmlns *ns;
 | 
						|
 | 
						|
  for(s=id->name; *s; s++)
 | 
						|
  { if ( *s == nschr )
 | 
						|
    { dtd_symbol *n;
 | 
						|
 | 
						|
      *o = '\0';
 | 
						|
      *local = s+1;
 | 
						|
      n = dtd_add_symbol(dtd, buf);
 | 
						|
 | 
						|
      if ( istrprefix(L"xml", buf) )	/* XML reserved namespaces */
 | 
						|
      { *url = n->name;
 | 
						|
        return TRUE;
 | 
						|
      } else if ( (ns = xmlns_find(p, n)) )
 | 
						|
      { if ( ns->url->name[0] )
 | 
						|
	  *url = ns->url->name;
 | 
						|
	else
 | 
						|
	  *url = NULL;
 | 
						|
	return TRUE;
 | 
						|
      } else
 | 
						|
      { *url = n->name;			/* undefined namespace */
 | 
						|
	if ( p->xml_no_ns == NONS_QUIET )
 | 
						|
	  return TRUE;
 | 
						|
	gripe(p, ERC_EXISTENCE, L"namespace", n->name);
 | 
						|
	return FALSE;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    *o++ = *s;
 | 
						|
  }
 | 
						|
 | 
						|
  *local = id->name;
 | 
						|
 | 
						|
  if ( (p->flags & SGML_PARSER_QUALIFY_ATTS) &&
 | 
						|
       (ns = p->environments->thisns) && ns->url->name[0] )
 | 
						|
    *url = ns->url->name;
 | 
						|
  else
 | 
						|
    *url = NULL;			/* no default namespace is defined */
 | 
						|
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
						|
Resolve the namespace for the current  element. This namespace is stored
 | 
						|
in the environment as `thisns' and  acts   as  default for resolving the
 | 
						|
namespaces of the attributes (see above).
 | 
						|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 | 
						|
 | 
						|
int
 | 
						|
xmlns_resolve_element(dtd_parser *p, const ichar **local, const ichar **url)
 | 
						|
{ sgml_environment *e;
 | 
						|
 | 
						|
  if ( (e=p->environments) )
 | 
						|
  { dtd_symbol *id = e->element->name;
 | 
						|
    dtd *dtd = p->dtd;
 | 
						|
    int nschr = dtd->charfunc->func[CF_NS]; /* : */
 | 
						|
    ichar buf[MAXNMLEN];
 | 
						|
    ichar *o = buf;
 | 
						|
    const ichar *s;
 | 
						|
    xmlns *ns;
 | 
						|
 | 
						|
    for(s=id->name; *s; s++)
 | 
						|
    { if ( *s == nschr )		/* explicit namespace */
 | 
						|
      { dtd_symbol *n;
 | 
						|
 | 
						|
	*o = '\0';
 | 
						|
	*local = s+1;
 | 
						|
	n = dtd_add_symbol(dtd, buf);
 | 
						|
 | 
						|
	if ( (ns = xmlns_find(p, n)) )
 | 
						|
	{ if ( ns->url->name[0] )
 | 
						|
	    *url = ns->url->name;
 | 
						|
	  else
 | 
						|
	    *url = NULL;
 | 
						|
	  e->thisns = ns;		/* default for attributes */
 | 
						|
	  return TRUE;
 | 
						|
	} else
 | 
						|
	{ *url = n->name;		/* undefined namespace */
 | 
						|
	  e->thisns = xmlns_push(p, n->name, n->name); /* define implicitly */
 | 
						|
	  if ( p->xml_no_ns == NONS_QUIET )
 | 
						|
	    return TRUE;
 | 
						|
	  gripe(p, ERC_EXISTENCE, L"namespace", n->name);
 | 
						|
	  return FALSE;
 | 
						|
	}
 | 
						|
      }
 | 
						|
      *o++ = *s;
 | 
						|
    }
 | 
						|
 | 
						|
    *local = id->name;
 | 
						|
 | 
						|
    if ( (ns = xmlns_find(p, NULL)) )
 | 
						|
    { if ( ns->url->name[0] )
 | 
						|
	*url = ns->url->name;
 | 
						|
      else
 | 
						|
	*url = NULL;
 | 
						|
      e->thisns = ns;
 | 
						|
    } else
 | 
						|
    { *url = NULL;			/* no default namespace is defined */
 | 
						|
      e->thisns = NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    return TRUE;
 | 
						|
  } else
 | 
						|
    return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#endif /*XMLNS*/
 | 
						|
 |