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*/
|
|
|