This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
yap-6.3/packages/sgml/xmlns.c
2010-05-06 10:59:09 +01:00

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