allow to inherit attributes from the DTD directly in the tree, this is
* SAX.c testXPath.c valid.c xmllint.c include/libxml/valid.h:
allow to inherit attributes from the DTD directly in the
tree, this is needed for XPath and can be a useful feature.
Inherited namespaces are always provided at the tree level now
* test/defattr* result/defattr* result/noent/defattr*: added a couple
of tests for this feature (XSLT being the prime user).
Daniel
diff --git a/ChangeLog b/ChangeLog
index 4dfea66..4b92af4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+Tue Aug 7 03:05:58 CEST 2001 Daniel Veillard <daniel@veillard.com>
+
+ * SAX.c testXPath.c valid.c xmllint.c include/libxml/valid.h:
+ allow to inherit attributes from the DTD directly in the
+ tree, this is needed for XPath and can be a useful feature.
+ Inherited namespaces are always provided at the tree level now
+ * test/defattr* result/defattr* result/noent/defattr*: added a couple
+ of tests for this feature (XSLT being the prime user).
+
Fri Aug 3 14:02:20 CEST 2001 Daniel Veillard <daniel@veillard.com>
* DOCBparser.c Makefile.am nanohttp.c parser.c testHTML.c
diff --git a/SAX.c b/SAX.c
index beac21e..86e95d7 100644
--- a/SAX.c
+++ b/SAX.c
@@ -21,6 +21,7 @@
#include <libxml/xmlIO.h>
#include <libxml/SAX.h>
#include <libxml/uri.h>
+#include <libxml/valid.h>
#include <libxml/HTMLtree.h>
/* #define DEBUG_SAX */
@@ -1033,6 +1034,78 @@
}
/*
+ * Insert all the defaulted attributes from the DTD especially namespaces
+ */
+ if ((!ctxt->html) &&
+ ((ctxt->myDoc->intSubset != NULL) ||
+ (ctxt->myDoc->extSubset != NULL))) {
+ xmlElementPtr elemDecl = NULL;
+
+ if (prefix != NULL) {
+ if (ctxt->myDoc->intSubset != NULL)
+ elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->intSubset,
+ name, prefix);
+ if ((elemDecl == NULL) && (ctxt->myDoc->extSubset != NULL))
+ elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset,
+ name, prefix);
+ } else {
+ if (ctxt->myDoc->intSubset != NULL)
+ elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->intSubset,
+ name, prefix);
+ if ((elemDecl == NULL) && (ctxt->myDoc->extSubset != NULL))
+ elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset,
+ name, prefix);
+ }
+ if (elemDecl != NULL) {
+ xmlAttributePtr attr = elemDecl->attributes;
+ while (attr != NULL) {
+ if (attr->defaultValue != NULL) {
+ /*
+ * the element should be instanciated in the tree if:
+ * - this is a namespace prefix
+ * - the user required for completion in the tree
+ * like XSLT
+ */
+ if (((attr->prefix != NULL) &&
+ (xmlStrEqual(attr->prefix, BAD_CAST "xmlns"))) ||
+ ((attr->prefix == NULL) &&
+ (xmlStrEqual(attr->name, BAD_CAST "xmlns"))) ||
+ (ctxt->loadsubset & XML_COMPLETE_ATTRS)) {
+ xmlChar buffer[100];
+ const xmlChar *fulln = attr->name;
+
+ if (attr->prefix != NULL) {
+ snprintf((char *) buffer, 99, "%s:%s",
+ attr->prefix, attr->name);
+ buffer[99] = 0;
+ fulln = buffer;
+ }
+
+ /*
+ * Check that the attribute is not declared in the
+ * serialization
+ */
+ att = NULL;
+ if (atts != NULL) {
+ i = 0;
+ att = atts[i];
+ while (att != NULL) {
+ if (xmlStrEqual(att, fulln))
+ break;
+ i += 2;
+ att = atts[i];
+ }
+ }
+ if (att == NULL)
+ attribute(ctxt, fulln, attr->defaultValue);
+ }
+ }
+ attr = attr->nexth;
+ }
+ }
+ }
+
+ /*
* process all the attributes whose name start with "xml"
*/
if (atts != NULL) {
diff --git a/include/libxml/valid.h b/include/libxml/valid.h
index 5b29e8d..276a2e4 100644
--- a/include/libxml/valid.h
+++ b/include/libxml/valid.h
@@ -230,8 +230,15 @@
xmlAttributePtr xmlGetDtdAttrDesc (xmlDtdPtr dtd,
const xmlChar *elem,
const xmlChar *name);
+xmlAttributePtr xmlGetDtdQAttrDesc (xmlDtdPtr dtd,
+ const xmlChar *elem,
+ const xmlChar *name,
+ const xmlChar *prefix);
xmlNotationPtr xmlGetDtdNotationDesc (xmlDtdPtr dtd,
const xmlChar *name);
+xmlElementPtr xmlGetDtdQElementDesc (xmlDtdPtr dtd,
+ const xmlChar *name,
+ const xmlChar *prefix);
xmlElementPtr xmlGetDtdElementDesc (xmlDtdPtr dtd,
const xmlChar *name);
diff --git a/result/defattr.xml b/result/defattr.xml
new file mode 100644
index 0000000..0a4ac15
--- /dev/null
+++ b/result/defattr.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<!DOCTYPE doc [
+<!ELEMENT doc EMPTY>
+<!ATTLIST doc xmlns CDATA #FIXED "http://www.example.com/">
+]>
+<doc xmlns="http://www.example.com/"/>
diff --git a/result/defattr2.xml b/result/defattr2.xml
new file mode 100644
index 0000000..8d1fc3b
--- /dev/null
+++ b/result/defattr2.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<!DOCTYPE doc [
+<!ELEMENT doc EMPTY>
+<!ATTLIST doc defatt (0 | 1) "0">
+<!ATTLIST doc xmlns:tst CDATA #FIXED "http://example.org">
+<!ATTLIST doc tst:att (0 | 1) "1">
+]>
+<doc xmlns:tst="http://example.org" att="1"/>
diff --git a/result/noent/defattr.xml b/result/noent/defattr.xml
new file mode 100644
index 0000000..0a4ac15
--- /dev/null
+++ b/result/noent/defattr.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<!DOCTYPE doc [
+<!ELEMENT doc EMPTY>
+<!ATTLIST doc xmlns CDATA #FIXED "http://www.example.com/">
+]>
+<doc xmlns="http://www.example.com/"/>
diff --git a/result/noent/defattr2.xml b/result/noent/defattr2.xml
new file mode 100644
index 0000000..8d1fc3b
--- /dev/null
+++ b/result/noent/defattr2.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<!DOCTYPE doc [
+<!ELEMENT doc EMPTY>
+<!ATTLIST doc defatt (0 | 1) "0">
+<!ATTLIST doc xmlns:tst CDATA #FIXED "http://example.org">
+<!ATTLIST doc tst:att (0 | 1) "1">
+]>
+<doc xmlns:tst="http://example.org" att="1"/>
diff --git a/test/defattr.xml b/test/defattr.xml
new file mode 100644
index 0000000..3f16a50
--- /dev/null
+++ b/test/defattr.xml
@@ -0,0 +1,6 @@
+<!DOCTYPE doc [
+<!ELEMENT doc EMPTY>
+<!ATTLIST doc
+ xmlns CDATA #FIXED "http://www.example.com/">
+]>
+<doc/>
diff --git a/test/defattr2.xml b/test/defattr2.xml
new file mode 100644
index 0000000..ab50709
--- /dev/null
+++ b/test/defattr2.xml
@@ -0,0 +1,8 @@
+<!DOCTYPE doc [
+<!ELEMENT doc EMPTY>
+<!ATTLIST doc
+ defatt (0|1) "0"
+ xmlns:tst CDATA #FIXED "http://example.org"
+ tst:att (0|1) "1">
+]>
+<doc att="1"/>
diff --git a/testXPath.c b/testXPath.c
index 983299d..04d09d2 100644
--- a/testXPath.c
+++ b/testXPath.c
@@ -175,6 +175,8 @@
usefile++;
}
if (valid != 0) xmlDoValidityCheckingDefaultValue = 1;
+ xmlLoadExtDtdDefaultValue |= XML_DETECT_IDS;
+ xmlLoadExtDtdDefaultValue |= XML_COMPLETE_ATTRS;
if (nocdata != 0) {
xmlDefaultSAXHandlerInit();
xmlDefaultSAXHandler.cdataBlock = NULL;
diff --git a/valid.c b/valid.c
index a0e9c0f..df25a70 100644
--- a/valid.c
+++ b/valid.c
@@ -1271,13 +1271,40 @@
*/
elemDef = xmlGetDtdElementDesc2(dtd, elem, 1);
if (elemDef != NULL) {
+
if ((type == XML_ATTRIBUTE_ID) &&
(xmlScanIDAttributeDecl(NULL, elemDef) != 0))
VERROR(ctxt->userData,
"Element %s has too may ID attributes defined : %s\n",
elem, name);
- ret->nexth = elemDef->attributes;
- elemDef->attributes = ret;
+ /*
+ * Insert namespace default def first they need to be
+ * processed firt.
+ */
+ if ((xmlStrEqual(ret->name, BAD_CAST "xmlns")) ||
+ ((ret->prefix != NULL &&
+ (xmlStrEqual(ret->prefix, BAD_CAST "xmlns"))))) {
+ ret->nexth = elemDef->attributes;
+ elemDef->attributes = ret;
+ } else {
+ xmlAttributePtr tmp = elemDef->attributes;
+
+ while ((tmp != NULL) &&
+ ((xmlStrEqual(tmp->name, BAD_CAST "xmlns")) ||
+ ((ret->prefix != NULL &&
+ (xmlStrEqual(ret->prefix, BAD_CAST "xmlns")))))) {
+ if (tmp->nexth == NULL)
+ break;
+ tmp = tmp->nexth;
+ }
+ if (tmp != NULL) {
+ ret->nexth = tmp->nexth;
+ tmp->nexth = ret;
+ } else {
+ ret->nexth = elemDef->attributes;
+ elemDef->attributes = ret;
+ }
+ }
}
/*
@@ -2280,7 +2307,7 @@
* returns the xmlElementPtr if found or NULL
*/
-static xmlElementPtr
+xmlElementPtr
xmlGetDtdQElementDesc(xmlDtdPtr dtd, const xmlChar *name,
const xmlChar *prefix) {
xmlElementTablePtr table;
@@ -2341,7 +2368,7 @@
* returns the xmlAttributePtr if found or NULL
*/
-static xmlAttributePtr
+xmlAttributePtr
xmlGetDtdQAttrDesc(xmlDtdPtr dtd, const xmlChar *elem, const xmlChar *name,
const xmlChar *prefix) {
xmlAttributeTablePtr table;
diff --git a/xmllint.c b/xmllint.c
index ee020df..6573c3c 100644
--- a/xmllint.c
+++ b/xmllint.c
@@ -97,6 +97,7 @@
#ifdef LIBXML_XINCLUDE_ENABLED
static int xinclude = 0;
#endif
+static int dtdattrs = 0;
static int loaddtd = 0;
static int progresult = 0;
static int timing = 0;
@@ -792,8 +793,9 @@
printf("\t--auto : generate a small doc on the fly\n");
#ifdef LIBXML_XINCLUDE_ENABLED
printf("\t--xinclude : do XInclude processing\n");
- printf("\t--loaddtd : fetch external Dtd\n");
#endif
+ printf("\t--loaddtd : fetch external Dtd\n");
+ printf("\t--dtdattr : loaddtd + populate the tree with inherited attributes \n");
}
int
main(int argc, char **argv) {
@@ -850,7 +852,11 @@
else if ((!strcmp(argv[i], "-loaddtd")) ||
(!strcmp(argv[i], "--loaddtd")))
loaddtd++;
- else if ((!strcmp(argv[i], "-valid")) ||
+ else if ((!strcmp(argv[i], "-dtdattr")) ||
+ (!strcmp(argv[i], "--dtdattr"))) {
+ loaddtd++;
+ dtdattrs++;
+ } else if ((!strcmp(argv[i], "-valid")) ||
(!strcmp(argv[i], "--valid")))
valid++;
else if ((!strcmp(argv[i], "-postvalid")) ||
@@ -946,7 +952,10 @@
}
}
xmlLineNumbersDefault(1);
- if (loaddtd != 0) xmlLoadExtDtdDefaultValue = 6; /* fetch DTDs by default */
+ if (loaddtd != 0)
+ xmlLoadExtDtdDefaultValue |= XML_DETECT_IDS;
+ if (dtdattrs)
+ xmlLoadExtDtdDefaultValue |= XML_COMPLETE_ATTRS;
if (noent != 0) xmlSubstituteEntitiesDefault(1);
if (valid != 0) xmlDoValidityCheckingDefaultValue = 1;
if ((htmlout) && (!nowrap)) {