XInclude and other stuff while travelling. Contributed patches:

- tree.[ch] xinclude.[ch] xmllint.c configure.in valid.c
  debugXML.c xmlversion.h.in: Started adding XInclude support,
  this is a new xmllint option
- tree.c xpath.c: applied TOM patches for XPath
- xpointer.c: fixed a couple of errors.
- uri.c: added an escaping function needed for xinclude
- testXPath.c hash.c HTMLtree.c: minor cleanups raised by
  new warning from RH70 gcc's version
Daniel
This commit is contained in:
Daniel Veillard 2000-11-06 16:43:11 +00:00
parent a4964b7500
commit 9e8bfae59a
22 changed files with 1453 additions and 206 deletions

View File

@ -1,3 +1,14 @@
Mon Nov 6 17:22:46 CET 2000 Daniel Veillard <Daniel.Veillard@w3.org>
* tree.[ch] xinclude.[ch] xmllint.c configure.in valid.c
debugXML.c xmlversion.h.in: Started adding XInclude support,
this is a new xmllint option
* tree.c xpath.c: applied TOM patches for XPath
* xpointer.c: fixed a couple of errors.
* uri.c: added an escaping function needed for xinclude
* testXPath.c hash.c HTMLtree.c: minor cleanups raised by
new warning from RH70 gcc's version
Tue Oct 31 14:14:13 CET 2000 Daniel Veillard <Daniel.Veillard@w3.org>
* HTMLparser.c: fixed loop on invalid char in scripts

View File

@ -818,7 +818,8 @@ htmlNodeDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, const
#ifndef XML_USE_BUFFER_CONTENT
xmlOutputBufferWriteString(buf, (const char *)cur->content);
#else
xmlOutputBufferWriteString(buf, xmlBufferContent(cur->content));
xmlOutputBufferWriteString(buf, (const char *)
xmlBufferContent(cur->content));
#endif
xmlOutputBufferWriteString(buf, "-->");
}
@ -835,7 +836,8 @@ htmlNodeDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, const
#ifndef XML_USE_BUFFER_CONTENT
xmlOutputBufferWriteString(buf, (const char *)cur->content);
#else
xmlOutputBufferWriteString(buf, xmlBufferContent(cur->content));
xmlOutputBufferWriteString(buf, (const char *)
xmlBufferContent(cur->content));
#endif
}
return;

View File

@ -34,6 +34,7 @@ libxml_la_SOURCES = \
debugXML.c \
xpath.c \
xpointer.c \
xinclude.c \
nanohttp.c \
nanoftp.c

View File

@ -286,6 +286,19 @@ fi
AC_SUBST(WITH_XPTR)
AC_SUBST(XPTR_OBJ)
AC_ARG_WITH(xinclude, [ --with-xinclude Add the XInclude support (on)])
if test "$with_xinclude" = "no" ; then
echo Disabling XInclude support
WITH_XINCLUDE=0
XINCLUDE_OBJ=
with_xinclude="no"
else
WITH_XINCLUDE=1
XINCLUDE_OBJ=xinclude.o
fi
AC_SUBST(WITH_XINCLUDE)
AC_SUBST(XINCLUDE_OBJ)
AC_ARG_WITH(iconv, [ --with-iconv Add the ICONV support (on)])
if test "$with_iconv" = "no" ; then
echo Disabling ICONV support

View File

@ -559,6 +559,7 @@ void xmlDebugDumpOneNode(FILE *output, xmlNodePtr node, int depth) {
fprintf(output, "DOCUMENT_FRAG\n");
break;
case XML_NOTATION_NODE:
fprintf(output, shift);
fprintf(output, "NOTATION\n");
break;
case XML_DTD_NODE:
@ -576,6 +577,14 @@ void xmlDebugDumpOneNode(FILE *output, xmlNodePtr node, int depth) {
case XML_NAMESPACE_DECL:
xmlDebugDumpNamespace(output, (xmlNsPtr) node, depth);
return;
case XML_XINCLUDE_START:
fprintf(output, shift);
fprintf(output, "INCLUDE START\n");
return;
case XML_XINCLUDE_END:
fprintf(output, shift);
fprintf(output, "INCLUDE END\n");
return;
default:
fprintf(output, shift);
fprintf(output, "NODE_%d !!!\n", node->type);
@ -917,6 +926,8 @@ static int xmlLsCountNode(xmlNodePtr node) {
case XML_ATTRIBUTE_DECL:
case XML_ENTITY_DECL:
case XML_NAMESPACE_DECL:
case XML_XINCLUDE_START:
case XML_XINCLUDE_END:
ret = 1;
break;
}

1
hash.c
View File

@ -17,6 +17,7 @@
* Author: bjorn.reese@systematic.dk
*/
#include <string.h>
#include <libxml/hash.h>
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>

View File

@ -41,9 +41,11 @@ typedef enum {
XML_ELEMENT_DECL= 15,
XML_ATTRIBUTE_DECL= 16,
XML_ENTITY_DECL= 17,
XML_NAMESPACE_DECL= 18
XML_NAMESPACE_DECL= 18,
XML_XINCLUDE_START= 19,
XML_XINCLUDE_END= 20
#ifdef LIBXML_SGML_ENABLED
,XML_SGML_DOCUMENT_NODE= 19
,XML_SGML_DOCUMENT_NODE= 21
#endif
} xmlElementType;

View File

@ -52,6 +52,7 @@ char * xmlURIUnescapeString (const char *str,
int len,
char *target);
int xmlNormalizeURIPath (char *path);
xmlChar * xmlURIEscape (const xmlChar *str);
void xmlFreeURI (xmlURIPtr uri);
#ifdef __cplusplus

26
include/libxml/xinclude.h Normal file
View File

@ -0,0 +1,26 @@
/*
* xinclude.c : API to handle XInclude processing
*
* World Wide Web Consortium Working Draft 26 October 2000
* http://www.w3.org/TR/2000/WD-xinclude-20001026
*
* See Copyright for the status of this software.
*
* Daniel.Veillard@w3.org
*/
#ifndef __XML_XINCLUDE_H__
#define __XML_XINCLUDE_H__
#include <libxml/tree.h>
#ifdef __cplusplus
extern "C" {
#endif
int xmlXIncludeProcess (xmlDocPtr doc);
#ifdef __cplusplus
}
#endif
#endif /* __XML_XINCLUDE_H__ */

View File

@ -77,6 +77,15 @@ extern void xmlCheckVersion(int version);
#define LIBXML_XPTR_DISABLED
#endif
/*
* Whether XInclude is configured in
*/
#if @WITH_XINCLUDE@
#define LIBXML_XINCLUDE_ENABLED
#else
#define LIBXML_XINCLUDE_DISABLED
#endif
/*
* Whether iconv support is available
*/

View File

@ -41,6 +41,7 @@
#include <libxml/debugXML.h>
#include <libxml/xmlmemory.h>
#include <libxml/parserInternals.h>
#include <libxml/xpathInternals.h>
#include <libxml/xmlerror.h>
#if defined(LIBXML_XPTR_ENABLED)
#include <libxml/xpointer.h>

218
tree.c
View File

@ -45,12 +45,16 @@ int xmlSaveNoEmptyTags = 0;
#define IS_BLANK(c) \
(((c) == '\n') || ((c) == '\r') || ((c) == '\t') || ((c) == ' '))
#define UPDATE_LAST_CHILD(n) if ((n) != NULL) { \
#define UPDATE_LAST_CHILD_AND_PARENT(n) if ((n) != NULL) { \
xmlNodePtr ulccur = (n)->children; \
if (ulccur == NULL) { \
(n)->last = NULL; \
} else { \
while (ulccur->next != NULL) ulccur = ulccur->next; \
while (ulccur->next != NULL) { \
ulccur->parent = (n); \
ulccur = ulccur->next; \
} \
ulccur->parent = (n); \
(n)->last = ulccur; \
}}
@ -892,6 +896,7 @@ xmlNewProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
buffer = xmlEncodeEntitiesReentrant(node->doc, value);
cur->children = xmlStringGetNodeList(node->doc, buffer);
cur->last = NULL;
tmp = cur->children;
while (tmp != NULL) {
tmp->parent = (xmlNodePtr) cur;
@ -965,6 +970,7 @@ xmlNewNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
buffer = xmlEncodeEntitiesReentrant(node->doc, value);
cur->children = xmlStringGetNodeList(node->doc, buffer);
cur->last = NULL;
tmp = cur->children;
while (tmp != NULL) {
tmp->parent = (xmlNodePtr) cur;
@ -1027,8 +1033,20 @@ xmlNewDocProp(xmlDocPtr doc, const xmlChar *name, const xmlChar *value) {
cur->name = xmlStrdup(name);
cur->doc = doc;
if (value != NULL)
if (value != NULL) {
xmlNodePtr tmp;
cur->children = xmlStringGetNodeList(doc, value);
cur->last = NULL;
tmp = cur->children;
while (tmp != NULL) {
tmp->parent = (xmlNodePtr) cur;
if (tmp->next == NULL)
cur->last = tmp;
tmp = tmp->next;
}
}
return(cur);
}
@ -1239,7 +1257,7 @@ xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns,
cur->doc = doc;
if (content != NULL) {
cur->children = xmlStringGetNodeList(doc, content);
UPDATE_LAST_CHILD(cur)
UPDATE_LAST_CHILD_AND_PARENT(cur)
}
}
return(cur);
@ -1268,7 +1286,7 @@ xmlNewDocRawNode(xmlDocPtr doc, xmlNsPtr ns,
cur->doc = doc;
if (content != NULL) {
cur->children = xmlNewDocText(doc, content);
UPDATE_LAST_CHILD(cur)
UPDATE_LAST_CHILD_AND_PARENT(cur)
}
}
return(cur);
@ -1491,7 +1509,13 @@ xmlNewReference(xmlDocPtr doc, const xmlChar *name) {
if (ent->content != NULL)
xmlBufferAdd(cur->content, ent->content, -1);
#endif
/*
* The parent pointer in entity is a Dtd pointer and thus is NOT
* updated. Not sure if this is 100% correct.
* -George
*/
cur->children = (xmlNodePtr) ent;
cur->last = (xmlNodePtr) ent;
}
return(cur);
}
@ -1662,6 +1686,47 @@ xmlNewDocComment(xmlDocPtr doc, const xmlChar *content) {
return(cur);
}
/**
* xmlSetTreeDoc:
* @tree: the top element
* @doc: the document
*
* update all nodes under the tree to point to the right document
*/
void
xmlSetTreeDoc(xmlNodePtr tree, xmlDocPtr doc) {
if (tree == NULL)
return;
if (tree->type == XML_ENTITY_DECL)
return;
if (tree->doc != doc) {
if (tree->children != NULL)
xmlSetListDoc(tree->children, doc);
tree->doc = doc;
}
}
/**
* xmlSetListDoc:
* @tree: the first element
* @doc: the document
*
* update all nodes in the list to point to the right document
*/
void
xmlSetListDoc(xmlNodePtr list, xmlDocPtr doc) {
xmlNodePtr cur;
if (list == NULL)
return;
cur = list;
while (cur != NULL) {
if (cur->doc != doc)
xmlSetTreeDoc(cur, doc);
cur = cur->next;
}
}
/**
* xmlNewChild:
@ -1779,7 +1844,8 @@ xmlAddNextSibling(xmlNodePtr cur, xmlNodePtr elem) {
xmlNodeSetContent(cur->next, tmp);
xmlFree(tmp);
#else
xmlBufferAddHead(cur->next, xmlBufferContent(elem->content),
xmlBufferAddHead(cur->next->content,
xmlBufferContent(elem->content),
xmlBufferLength(elem->content));
#endif
xmlFreeNode(elem);
@ -1787,7 +1853,9 @@ xmlAddNextSibling(xmlNodePtr cur, xmlNodePtr elem) {
}
}
elem->doc = cur->doc;
if (elem->doc != cur->doc) {
xmlSetTreeDoc(elem, cur->doc);
}
elem->parent = cur->parent;
elem->prev = cur;
elem->next = cur->next;
@ -1857,7 +1925,9 @@ xmlAddPrevSibling(xmlNodePtr cur, xmlNodePtr elem) {
}
}
elem->doc = cur->doc;
if (elem->doc != cur->doc) {
xmlSetTreeDoc(elem, cur->doc);
}
elem->parent = cur->parent;
elem->next = cur;
elem->prev = cur->prev;
@ -1926,9 +1996,9 @@ xmlAddSibling(xmlNodePtr cur, xmlNodePtr elem) {
return(cur);
}
if (elem->doc == NULL)
elem->doc = cur->doc; /* the parent may not be linked to a doc ! */
if (elem->doc != cur->doc) {
xmlSetTreeDoc(elem, cur->doc);
}
parent = cur->parent;
elem->prev = cur;
elem->next = NULL;
@ -2011,7 +2081,9 @@ xmlAddChildList(xmlNodePtr parent, xmlNodePtr cur) {
}
while (cur->next != NULL) {
cur->parent = parent;
cur->doc = parent->doc; /* the parent may not be linked to a doc ! */
if (cur->doc != parent->doc) {
xmlSetTreeDoc(cur, parent->doc);
}
cur = cur->next;
}
cur->parent = parent;
@ -2090,7 +2162,9 @@ xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) {
* add the new element at the end of the children list.
*/
cur->parent = parent;
cur->doc = parent->doc; /* the parent may not be linked to a doc ! */
if (cur->doc != parent->doc) {
xmlSetTreeDoc(cur, parent->doc);
}
/*
* Handle the case where parent->content != NULL, in that case it will
@ -2110,7 +2184,7 @@ xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) {
if (text->next != NULL)
text->next->prev = text;
parent->children = text;
UPDATE_LAST_CHILD(parent)
UPDATE_LAST_CHILD_AND_PARENT(parent)
#ifndef XML_USE_BUFFER_CONTENT
xmlFree(parent->content);
#else
@ -2264,6 +2338,9 @@ xmlReplaceNode(xmlNodePtr old, xmlNodePtr cur) {
xmlUnlinkNode(old);
return(old);
}
if (cur == old) {
return(old);
}
xmlUnlinkNode(cur);
cur->doc = old->doc;
cur->parent = old->parent;
@ -2374,8 +2451,19 @@ xmlCopyProp(xmlNodePtr target, xmlAttrPtr cur) {
} else
ret->ns = NULL;
if (cur->children != NULL)
if (cur->children != NULL) {
xmlNodePtr tmp;
ret->children = xmlCopyNodeList(cur->children);
ret->last = NULL;
tmp = ret->children;
while (tmp != NULL) {
tmp->parent = (xmlNodePtr)ret;
if (tmp->next == NULL)
ret->last = tmp;
tmp = tmp->next;
}
}
return(ret);
}
@ -2494,7 +2582,7 @@ xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
ret->properties = xmlCopyPropList(ret, node->properties);
if (node->children != NULL)
ret->children = xmlStaticCopyNodeList(node->children, doc, ret);
UPDATE_LAST_CHILD(ret)
UPDATE_LAST_CHILD_AND_PARENT(ret)
return(ret);
}
@ -2633,9 +2721,18 @@ xmlCopyDoc(xmlDocPtr doc, int recursive) {
ret->intSubset = xmlCopyDtd(doc->intSubset);
if (doc->oldNs != NULL)
ret->oldNs = xmlCopyNamespaceList(doc->oldNs);
if (doc->children != NULL)
if (doc->children != NULL) {
xmlNodePtr tmp;
ret->children = xmlStaticCopyNodeList(doc->children, ret,
(xmlNodePtr)ret);
ret->last = NULL;
tmp = ret->children;
while (tmp != NULL) {
if (tmp->next == NULL)
ret->last = tmp;
tmp = tmp->next;
}
}
return(ret);
}
@ -2692,6 +2789,7 @@ xmlDocSetRootElement(xmlDocPtr doc, xmlNodePtr root) {
if (old == NULL) {
if (doc->children == NULL) {
doc->children = root;
doc->last = root;
} else {
xmlAddSibling(doc->children, root);
}
@ -2732,6 +2830,8 @@ xmlNodeSetLang(xmlNodePtr cur, const xmlChar *lang) {
#ifdef LIBXML_SGML_ENABLED
case XML_SGML_DOCUMENT_NODE:
#endif
case XML_XINCLUDE_START:
case XML_XINCLUDE_END:
return;
case XML_ELEMENT_NODE:
case XML_ATTRIBUTE_NODE:
@ -2792,6 +2892,8 @@ xmlNodeSetSpacePreserve(xmlNodePtr cur, int val) {
case XML_ENTITY_REF_NODE:
case XML_ENTITY_NODE:
case XML_NAMESPACE_DECL:
case XML_XINCLUDE_START:
case XML_XINCLUDE_END:
#ifdef LIBXML_SGML_ENABLED
case XML_SGML_DOCUMENT_NODE:
#endif
@ -2863,6 +2965,8 @@ xmlNodeSetName(xmlNodePtr cur, const xmlChar *name) {
case XML_NOTATION_NODE:
case XML_HTML_DOCUMENT_NODE:
case XML_NAMESPACE_DECL:
case XML_XINCLUDE_START:
case XML_XINCLUDE_END:
#ifdef LIBXML_SGML_ENABLED
case XML_SGML_DOCUMENT_NODE:
#endif
@ -2911,6 +3015,8 @@ xmlNodeSetBase(xmlNodePtr cur, xmlChar* uri) {
case XML_ENTITY_REF_NODE:
case XML_ENTITY_NODE:
case XML_NAMESPACE_DECL:
case XML_XINCLUDE_START:
case XML_XINCLUDE_END:
#ifdef LIBXML_SGML_ENABLED
case XML_SGML_DOCUMENT_NODE:
#endif
@ -2922,6 +3028,34 @@ xmlNodeSetBase(xmlNodePtr cur, xmlChar* uri) {
xmlSetProp(cur, BAD_CAST "xml:base", uri);
}
/**
* xmlDocumentGetBase:
* @doc: the document
*
* Searches for the Document BASE URL. The code should work on both XML
* and HTML document.
* It returns the base as defined in RFC 2396 section
* 5.1.3. Base URI from the Retrieval URI
* However it does not return the computed base (5.1.1 and 5.1.2), use
* xmlNodeGetBase() for this
*
* Returns a pointer to the base URL, or NULL if not found
* It's up to the caller to free the memory.
*/
xmlChar *
xmlDocumentGetBase(xmlDocPtr doc) {
if (doc == NULL)
return(NULL);
if (doc->type == XML_HTML_DOCUMENT_NODE) {
if (doc->URL != NULL)
return(xmlStrdup(doc->URL));
return(NULL);
}
if (doc->URL != NULL)
return(xmlStrdup(doc->URL));
return(NULL);
}
/**
* xmlNodeGetBase:
* @doc: the document the node pertains to
@ -2929,6 +3063,12 @@ xmlNodeSetBase(xmlNodePtr cur, xmlChar* uri) {
*
* Searches for the BASE URL. The code should work on both XML
* and HTML document even if base mechanisms are completely different.
* It returns the base as defined in RFC 2396 sections
* 5.1.1. Base URI within Document Content
* and
* 5.1.2. Base URI from the Encapsulating Entity
* However it does not return the document base (5.1.3), use
* xmlDocumentGetBase() for this
*
* Returns a pointer to the base URL, or NULL if not found
* It's up to the caller to free the memory.
@ -2943,9 +3083,6 @@ xmlNodeGetBase(xmlDocPtr doc, xmlNodePtr cur) {
if ((doc != NULL) && (doc->type == XML_HTML_DOCUMENT_NODE)) {
cur = doc->children;
while ((cur != NULL) && (cur->name != NULL)) {
if (cur->type == XML_ENTITY_DECL) {
/* TODO: we are crossing entity boundaries */
}
if (cur->type != XML_ELEMENT_NODE) {
cur = cur->next;
continue;
@ -2963,18 +3100,18 @@ xmlNodeGetBase(xmlDocPtr doc, xmlNodePtr cur) {
}
cur = cur->next;
}
if ((doc != NULL) && (doc->URL != NULL))
return(xmlStrdup(doc->URL));
return(NULL);
}
while (cur != NULL) {
if (cur->type == XML_ENTITY_DECL) {
xmlEntityPtr ent = (xmlEntityPtr) cur;
return(xmlStrdup(ent->URI));
}
base = xmlGetProp(cur, BAD_CAST "xml:base");
if (base != NULL)
return(base);
cur = cur->parent;
}
if ((doc != NULL) && (doc->URL != NULL))
return(xmlStrdup(doc->URL));
return(NULL);
}
@ -3026,13 +3163,14 @@ xmlNodeGetContent(xmlNodePtr cur) {
case XML_DOCUMENT_TYPE_NODE:
case XML_NOTATION_NODE:
case XML_DTD_NODE:
case XML_XINCLUDE_START:
case XML_XINCLUDE_END:
#ifdef LIBXML_SGML_ENABLED
case XML_SGML_DOCUMENT_NODE:
#endif
return(NULL);
case XML_NAMESPACE_DECL:
/* TODO !!! */
return(NULL);
return(xmlStrdup(((xmlNsPtr)cur)->href));
case XML_ELEMENT_DECL:
/* TODO !!! */
return(NULL);
@ -3084,7 +3222,7 @@ xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content) {
}
if (cur->children != NULL) xmlFreeNodeList(cur->children);
cur->children = xmlStringGetNodeList(cur->doc, content);
UPDATE_LAST_CHILD(cur)
UPDATE_LAST_CHILD_AND_PARENT(cur)
break;
case XML_ATTRIBUTE_NODE:
break;
@ -3118,6 +3256,8 @@ xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content) {
case XML_DOCUMENT_NODE:
case XML_HTML_DOCUMENT_NODE:
case XML_DOCUMENT_TYPE_NODE:
case XML_XINCLUDE_START:
case XML_XINCLUDE_END:
#ifdef LIBXML_SGML_ENABLED
case XML_SGML_DOCUMENT_NODE:
#endif
@ -3170,7 +3310,7 @@ xmlNodeSetContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
}
if (cur->children != NULL) xmlFreeNodeList(cur->children);
cur->children = xmlStringLenGetNodeList(cur->doc, content, len);
UPDATE_LAST_CHILD(cur)
UPDATE_LAST_CHILD_AND_PARENT(cur)
break;
case XML_ATTRIBUTE_NODE:
break;
@ -3207,6 +3347,8 @@ xmlNodeSetContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
case XML_HTML_DOCUMENT_NODE:
case XML_DOCUMENT_TYPE_NODE:
case XML_NAMESPACE_DECL:
case XML_XINCLUDE_START:
case XML_XINCLUDE_END:
#ifdef LIBXML_SGML_ENABLED
case XML_SGML_DOCUMENT_NODE:
#endif
@ -3256,7 +3398,7 @@ xmlNodeAddContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
cur->children = xmlStringGetNodeList(cur->doc,
xmlBufferContent(cur->content));
#endif
UPDATE_LAST_CHILD(cur)
UPDATE_LAST_CHILD_AND_PARENT(cur)
#ifndef XML_USE_BUFFER_CONTENT
xmlFree(cur->content);
#else
@ -3296,6 +3438,8 @@ xmlNodeAddContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
case XML_HTML_DOCUMENT_NODE:
case XML_DOCUMENT_TYPE_NODE:
case XML_NAMESPACE_DECL:
case XML_XINCLUDE_START:
case XML_XINCLUDE_END:
#ifdef LIBXML_SGML_ENABLED
case XML_SGML_DOCUMENT_NODE:
#endif
@ -3944,12 +4088,14 @@ xmlSetProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
if (prop->children != NULL)
xmlFreeNodeList(prop->children);
prop->children = NULL;
prop->last = NULL;
if (value != NULL) {
xmlChar *buffer;
xmlNodePtr tmp;
buffer = xmlEncodeEntitiesReentrant(node->doc, value);
prop->children = xmlStringGetNodeList(node->doc, buffer);
prop->last = NULL;
tmp = prop->children;
while (tmp != NULL) {
tmp->parent = (xmlNodePtr) prop;
@ -3993,12 +4139,16 @@ xmlNodeIsText(xmlNodePtr node) {
*/
int
xmlIsBlankNode(xmlNodePtr node) {
xmlChar *cur;
const xmlChar *cur;
if (node == NULL) return(0);
if (node->type != XML_TEXT_NODE) return(0);
if (node->content == NULL) return(1);
#ifndef XML_USE_BUFFER_CONTENT
cur = node->content;
#else
cur = xmlBufferContent(node->content);
#endif
while (*cur != 0) {
if (!IS_BLANK(*cur)) return(0);
cur++;
@ -4749,6 +4899,10 @@ xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
#endif
return;
}
if (cur->type == XML_XINCLUDE_START)
return;
if (cur->type == XML_XINCLUDE_END)
return;
if (cur->type == XML_DTD_NODE) {
xmlDtdDump(buf, (xmlDtdPtr) cur);
return;
@ -5201,6 +5355,10 @@ xmlNodeDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur,
#endif
return;
}
if (cur->type == XML_XINCLUDE_START)
return;
if (cur->type == XML_XINCLUDE_END)
return;
if (cur->type == XML_DTD_NODE) {
xmlDtdDumpOutput(buf, (xmlDtdPtr) cur, encoding);
return;

6
tree.h
View File

@ -41,9 +41,11 @@ typedef enum {
XML_ELEMENT_DECL= 15,
XML_ATTRIBUTE_DECL= 16,
XML_ENTITY_DECL= 17,
XML_NAMESPACE_DECL= 18
XML_NAMESPACE_DECL= 18,
XML_XINCLUDE_START= 19,
XML_XINCLUDE_END= 20
#ifdef LIBXML_SGML_ENABLED
,XML_SGML_DOCUMENT_NODE= 19
,XML_SGML_DOCUMENT_NODE= 21
#endif
} xmlElementType;

353
uri.c
View File

@ -22,6 +22,13 @@
#include <libxml/uri.h>
#include <libxml/xmlerror.h>
/************************************************************************
* *
* Macros to differenciate various character type *
* directly extracted from RFC 2396 *
* *
************************************************************************/
/*
* alpha = lowalpha | upalpha
*/
@ -169,6 +176,12 @@
* path = [ abs_path | opaque_part ]
*/
/************************************************************************
* *
* Generic URI structure functions *
* *
************************************************************************/
/**
* xmlCreateURI:
*
@ -587,6 +600,143 @@ xmlFreeURI(xmlURIPtr uri) {
xmlFree(uri);
}
/************************************************************************
* *
* Helper functions *
* *
************************************************************************/
/**
* xmlNormalizeURIPath:
* @path: pointer to the path string
*
* applies the 5 normalization steps to a path string
* Normalization occurs directly on the string, no new allocation is done
*
* Returns 0 or an error code
*/
int
xmlNormalizeURIPath(char *path) {
int cur, out;
if (path == NULL)
return(-1);
cur = 0;
out = 0;
while ((path[cur] != 0) && (path[cur] != '/')) cur++;
if (path[cur] == 0)
return(0);
/* we are positionned at the beginning of the first segment */
cur++;
out = cur;
/*
* Analyze each segment in sequence.
*/
while (path[cur] != 0) {
/*
* c) All occurrences of "./", where "." is a complete path segment,
* are removed from the buffer string.
*/
if ((path[cur] == '.') && (path[cur + 1] == '/')) {
cur += 2;
continue;
}
/*
* d) If the buffer string ends with "." as a complete path segment,
* that "." is removed.
*/
if ((path[cur] == '.') && (path[cur + 1] == 0)) {
path[out] = 0;
break;
}
/* read the segment */
while ((path[cur] != 0) && (path[cur] != '/')) {
path[out++] = path[cur++];
}
path[out++] = path[cur];
if (path[cur] != 0) {
cur++;
}
}
cur = 0;
out = 0;
while ((path[cur] != 0) && (path[cur] != '/')) cur++;
if (path[cur] == 0)
return(0);
/* we are positionned at the beginning of the first segment */
cur++;
out = cur;
/*
* Analyze each segment in sequence.
*/
while (path[cur] != 0) {
/*
* e) All occurrences of "<segment>/../", where <segment> is a
* complete path segment not equal to "..", are removed from the
* buffer string. Removal of these path segments is performed
* iteratively, removing the leftmost matching pattern on each
* iteration, until no matching pattern remains.
*/
if ((cur > 1) && (out > 1) &&
(path[cur] == '/') && (path[cur + 1] == '.') &&
(path[cur + 2] == '.') && (path[cur + 3] == '/') &&
((path[out] != '.') || (path[out - 1] != '.') ||
(path[out - 2] != '/'))) {
cur += 3;
out --;
while ((out > 0) && (path[out] != '/')) { out --; }
path[out] = 0;
continue;
}
/*
* f) If the buffer string ends with "<segment>/..", where <segment>
* is a complete path segment not equal to "..", that
* "<segment>/.." is removed.
*/
if ((path[cur] == '/') && (path[cur + 1] == '.') &&
(path[cur + 2] == '.') && (path[cur + 3] == 0) &&
((path[out] != '.') || (path[out - 1] != '.') ||
(path[out - 2] != '/'))) {
cur += 4;
out --;
while ((out > 0) && (path[out - 1] != '/')) { out --; }
path[out] = 0;
continue;
}
path[out++] = path[cur++]; /* / or 0 */
}
path[out] = 0;
/*
* g) If the resulting buffer string still begins with one or more
* complete path segments of "..", then the reference is
* considered to be in error. Implementations may handle this
* error by retaining these components in the resolved path (i.e.,
* treating them as part of the final URI), by removing them from
* the resolved path (i.e., discarding relative levels above the
* root), or by avoiding traversal of the reference.
*
* We discard them from the final path.
*/
cur = 0;
while ((path[cur] == '/') && (path[cur + 1] == '.') &&
(path[cur + 2] == '.'))
cur += 3;
if (cur != 0) {
out = 0;
while (path[cur] != 0) path[out++] = path[cur++];
path[out] = 0;
}
return(0);
}
/**
* xmlURIUnescapeString:
* @str: the string to unescape
@ -647,6 +797,74 @@ xmlURIUnescapeString(const char *str, int len, char *target) {
return(ret);
}
/**
* xmlURIEscape:
* @str: the string of the URI to escape
*
* Escaping routine, does not do validity checks !
* It will try to escape the chars needing this, but this is heuristic
* based it's impossible to be sure.
*
* Returns an copy of the string, but escaped
*/
xmlChar *
xmlURIEscape(const xmlChar *str) {
xmlChar *ret;
const xmlChar *in;
unsigned int len, out;
if (str == NULL)
return(NULL);
len = xmlStrlen(str);
if (len <= 0) return(NULL);
len += 20;
ret = (xmlChar *) xmlMalloc(len);
if (ret == NULL) {
xmlGenericError(xmlGenericErrorContext,
"xmlURIEscape: out of memory\n");
return(NULL);
}
in = (const xmlChar *) str;
out = 0;
while(*in != 0) {
if (len - out <= 3) {
len += 20;
ret = (xmlChar *) xmlRealloc(ret, len);
if (ret == NULL) {
xmlGenericError(xmlGenericErrorContext,
"xmlURIEscape: out of memory\n");
return(NULL);
}
}
if ((!IS_UNRESERVED(*in)) && (*in != ':') && (*in != '/') &&
(*in != '?') && (*in != '#')) {
unsigned char val;
ret[out++] = '%';
val = *in >> 4;
if (val <= 9)
ret[out++] = '0' + val;
else
ret[out++] = 'A' + val - 0xA;
val = *in & 0xF;
if (val <= 9)
ret[out++] = '0' + val;
else
ret[out++] = 'A' + val - 0xA;
in++;
} else {
ret[out++] = *in++;
}
}
ret[out] = 0;
return(ret);
}
/************************************************************************
* *
* Escaped URI parsing *
* *
************************************************************************/
/**
* xmlParseURIFragment:
@ -1284,136 +1502,11 @@ xmlParseURI(const char *str) {
return(uri);
}
/**
* xmlNormalizeURIPath:
* @path: pointer to the path string
*
* applies the 5 normalization steps to a path string
* Normalization occurs directly on the string, no new allocation is done
*
* Returns 0 or an error code
*/
int
xmlNormalizeURIPath(char *path) {
int cur, out;
if (path == NULL)
return(-1);
cur = 0;
out = 0;
while ((path[cur] != 0) && (path[cur] != '/')) cur++;
if (path[cur] == 0)
return(0);
/* we are positionned at the beginning of the first segment */
cur++;
out = cur;
/*
* Analyze each segment in sequence.
*/
while (path[cur] != 0) {
/*
* c) All occurrences of "./", where "." is a complete path segment,
* are removed from the buffer string.
*/
if ((path[cur] == '.') && (path[cur + 1] == '/')) {
cur += 2;
continue;
}
/*
* d) If the buffer string ends with "." as a complete path segment,
* that "." is removed.
*/
if ((path[cur] == '.') && (path[cur + 1] == 0)) {
path[out] = 0;
break;
}
/* read the segment */
while ((path[cur] != 0) && (path[cur] != '/')) {
path[out++] = path[cur++];
}
path[out++] = path[cur];
if (path[cur] != 0) {
cur++;
}
}
cur = 0;
out = 0;
while ((path[cur] != 0) && (path[cur] != '/')) cur++;
if (path[cur] == 0)
return(0);
/* we are positionned at the beginning of the first segment */
cur++;
out = cur;
/*
* Analyze each segment in sequence.
*/
while (path[cur] != 0) {
/*
* e) All occurrences of "<segment>/../", where <segment> is a
* complete path segment not equal to "..", are removed from the
* buffer string. Removal of these path segments is performed
* iteratively, removing the leftmost matching pattern on each
* iteration, until no matching pattern remains.
*/
if ((cur > 1) && (out > 1) &&
(path[cur] == '/') && (path[cur + 1] == '.') &&
(path[cur + 2] == '.') && (path[cur + 3] == '/') &&
((path[out] != '.') || (path[out - 1] != '.') ||
(path[out - 2] != '/'))) {
cur += 3;
out --;
while ((out > 0) && (path[out] != '/')) { out --; }
path[out] = 0;
continue;
}
/*
* f) If the buffer string ends with "<segment>/..", where <segment>
* is a complete path segment not equal to "..", that
* "<segment>/.." is removed.
*/
if ((path[cur] == '/') && (path[cur + 1] == '.') &&
(path[cur + 2] == '.') && (path[cur + 3] == 0) &&
((path[out] != '.') || (path[out - 1] != '.') ||
(path[out - 2] != '/'))) {
cur += 4;
out --;
while ((out > 0) && (path[out - 1] != '/')) { out --; }
path[out] = 0;
continue;
}
path[out++] = path[cur++]; /* / or 0 */
}
path[out] = 0;
/*
* g) If the resulting buffer string still begins with one or more
* complete path segments of "..", then the reference is
* considered to be in error. Implementations may handle this
* error by retaining these components in the resolved path (i.e.,
* treating them as part of the final URI), by removing them from
* the resolved path (i.e., discarding relative levels above the
* root), or by avoiding traversal of the reference.
*
* We discard them from the final path.
*/
cur = 0;
while ((path[cur] == '/') && (path[cur + 1] == '.') &&
(path[cur + 2] == '.'))
cur += 3;
if (cur != 0) {
out = 0;
while (path[cur] != 0) path[out++] = path[cur++];
path[out] = 0;
}
return(0);
}
/************************************************************************
* *
* Public functions *
* *
************************************************************************/
/**
* xmlBuildURI:

1
uri.h
View File

@ -52,6 +52,7 @@ char * xmlURIUnescapeString (const char *str,
int len,
char *target);
int xmlNormalizeURIPath (char *path);
xmlChar * xmlURIEscape (const xmlChar *str);
void xmlFreeURI (xmlURIPtr uri);
#ifdef __cplusplus

View File

@ -3212,6 +3212,7 @@ xmlSprintfElementChilds(char *buf, xmlNodePtr node, int glob) {
case XML_DOCUMENT_TYPE_NODE:
case XML_DOCUMENT_FRAG_NODE:
case XML_NOTATION_NODE:
case XML_NAMESPACE_DECL:
strcat(buf, "???");
if (cur->next != NULL)
strcat(buf, " ");
@ -3223,6 +3224,8 @@ xmlSprintfElementChilds(char *buf, xmlNodePtr node, int glob) {
case XML_ELEMENT_DECL:
case XML_ATTRIBUTE_DECL:
case XML_ENTITY_DECL:
case XML_XINCLUDE_START:
case XML_XINCLUDE_END:
break;
}
cur = cur->next;

737
xinclude.c Normal file
View File

@ -0,0 +1,737 @@
/*
* xinclude.c : Code to implement XInclude processing
*
* World Wide Web Consortium Working Draft 26 October 2000
* http://www.w3.org/TR/2000/WD-xinclude-20001026
*
* See Copyright for the status of this software.
*
* Daniel.Veillard@w3.org
*/
/*
* TODO: compute XPointers nodesets
*/
#ifdef WIN32
#include "win32config.h"
#else
#include "config.h"
#endif
#include <stdio.h>
#include <string.h>
#include <libxml/xmlmemory.h>
#include <libxml/tree.h>
#include <libxml/parser.h>
#include <libxml/uri.h>
#include <libxml/xpointer.h>
#include <libxml/parserInternals.h>
#ifdef LIBXML_DEBUG_ENABLED
#include <libxml/debugXML.h>
#endif
#include <libxml/xmlerror.h>
#ifdef LIBXML_XINCLUDE_ENABLED
#include <libxml/xinclude.h>
#define XINCLUDE_NS (const xmlChar *) "http://www.w3.org/1999/XML/xinclude"
#define XINCLUDE_NODE (const xmlChar *) "include"
#define XINCLUDE_HREF (const xmlChar *) "href"
#define XINCLUDE_PARSE (const xmlChar *) "parse"
#define XINCLUDE_PARSE_XML (const xmlChar *) "xml"
#define XINCLUDE_PARSE_TEXT (const xmlChar *) "text"
/* #define DEBUG_XINCLUDE */
/************************************************************************
* *
* XInclude contexts handling *
* *
************************************************************************/
/*
* An XInclude context
*/
typedef xmlChar *URL;
typedef struct _xmlXIncludeCtxt xmlXIncludeCtxt;
typedef xmlXIncludeCtxt *xmlXIncludeCtxtPtr;
struct _xmlXIncludeCtxt {
xmlDocPtr doc; /* the source document */
int incNr; /* number of includes */
int incMax; /* size of includes tab */
xmlNodePtr *incTab; /* array of include nodes */
xmlNodePtr *repTab; /* array of replacement node lists */
int docNr; /* number of parsed documents */
int docMax; /* size of parsed documents tab */
xmlDocPtr *docTab; /* array of parsed documents */
URL *urlTab; /* array of parsed documents URLs */
int txtNr; /* number of unparsed documents */
int txtMax; /* size of unparsed documents tab */
xmlNodePtr *txtTab; /* array of unparsed text nodes */
URL *txturlTab; /* array of unparsed txtuments URLs */
};
/**
* xmlXIncludeAddNode:
* @ctxt: the XInclude context
* @node: the new node
*
* Add a new node to process to an XInclude context
*/
void
xmlXIncludeAddNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
if (ctxt->incMax == 0) {
ctxt->incMax = 4;
ctxt->incTab = (xmlNodePtr *) xmlMalloc(ctxt->incMax *
sizeof(ctxt->incTab[0]));
if (ctxt->incTab == NULL) {
xmlGenericError(xmlGenericErrorContext,
"malloc failed !\n");
return;
}
ctxt->repTab = (xmlNodePtr *) xmlMalloc(ctxt->incMax *
sizeof(ctxt->repTab[0]));
if (ctxt->repTab == NULL) {
xmlGenericError(xmlGenericErrorContext,
"malloc failed !\n");
return;
}
}
if (ctxt->incNr >= ctxt->incMax) {
ctxt->incMax *= 2;
ctxt->incTab = (xmlNodePtr *) xmlRealloc(ctxt->incTab,
ctxt->incMax * sizeof(ctxt->incTab[0]));
if (ctxt->incTab == NULL) {
xmlGenericError(xmlGenericErrorContext,
"realloc failed !\n");
return;
}
ctxt->repTab = (xmlNodePtr *) xmlRealloc(ctxt->repTab,
ctxt->incMax * sizeof(ctxt->repTab[0]));
if (ctxt->repTab == NULL) {
xmlGenericError(xmlGenericErrorContext,
"realloc failed !\n");
return;
}
}
ctxt->incTab[ctxt->incNr] = node;
ctxt->repTab[ctxt->incNr] = NULL;
ctxt->incNr++;
}
/**
* xmlXIncludeAddDoc:
* @ctxt: the XInclude context
* @doc: the new document
* @url: the associated URL
*
* Add a new document to the list
*/
void
xmlXIncludeAddDoc(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, const URL url) {
if (ctxt->docMax == 0) {
ctxt->docMax = 4;
ctxt->docTab = (xmlDocPtr *) xmlMalloc(ctxt->docMax *
sizeof(ctxt->docTab[0]));
if (ctxt->docTab == NULL) {
xmlGenericError(xmlGenericErrorContext,
"malloc failed !\n");
return;
}
ctxt->urlTab = (URL *) xmlMalloc(ctxt->docMax *
sizeof(ctxt->urlTab[0]));
if (ctxt->urlTab == NULL) {
xmlGenericError(xmlGenericErrorContext,
"malloc failed !\n");
return;
}
}
if (ctxt->docNr >= ctxt->docMax) {
ctxt->docMax *= 2;
ctxt->docTab = (xmlDocPtr *) xmlRealloc(ctxt->docTab,
ctxt->docMax * sizeof(ctxt->docTab[0]));
if (ctxt->docTab == NULL) {
xmlGenericError(xmlGenericErrorContext,
"realloc failed !\n");
return;
}
ctxt->urlTab = (URL *) xmlRealloc(ctxt->urlTab,
ctxt->docMax * sizeof(ctxt->urlTab[0]));
if (ctxt->urlTab == NULL) {
xmlGenericError(xmlGenericErrorContext,
"realloc failed !\n");
return;
}
}
ctxt->docTab[ctxt->docNr] = doc;
ctxt->urlTab[ctxt->docNr] = xmlStrdup(url);
ctxt->docNr++;
}
/**
* xmlXIncludeAddTxt:
* @ctxt: the XInclude context
* @txt: the new text node
* @url: the associated URL
*
* Add a new txtument to the list
*/
void
xmlXIncludeAddTxt(xmlXIncludeCtxtPtr ctxt, xmlNodePtr txt, const URL url) {
if (ctxt->txtMax == 0) {
ctxt->txtMax = 4;
ctxt->txtTab = (xmlNodePtr *) xmlMalloc(ctxt->txtMax *
sizeof(ctxt->txtTab[0]));
if (ctxt->txtTab == NULL) {
xmlGenericError(xmlGenericErrorContext,
"malloc failed !\n");
return;
}
ctxt->txturlTab = (URL *) xmlMalloc(ctxt->txtMax *
sizeof(ctxt->txturlTab[0]));
if (ctxt->txturlTab == NULL) {
xmlGenericError(xmlGenericErrorContext,
"malloc failed !\n");
return;
}
}
if (ctxt->txtNr >= ctxt->txtMax) {
ctxt->txtMax *= 2;
ctxt->txtTab = (xmlNodePtr *) xmlRealloc(ctxt->txtTab,
ctxt->txtMax * sizeof(ctxt->txtTab[0]));
if (ctxt->txtTab == NULL) {
xmlGenericError(xmlGenericErrorContext,
"realloc failed !\n");
return;
}
ctxt->txturlTab = (URL *) xmlRealloc(ctxt->txturlTab,
ctxt->txtMax * sizeof(ctxt->urlTab[0]));
if (ctxt->txturlTab == NULL) {
xmlGenericError(xmlGenericErrorContext,
"realloc failed !\n");
return;
}
}
ctxt->txtTab[ctxt->txtNr] = txt;
ctxt->txturlTab[ctxt->txtNr] = xmlStrdup(url);
ctxt->txtNr++;
}
/**
* xmlXIncludeNewContext:
* @doc: an XML Document
*
* Creates a new XInclude context
*
* Returns the new set
*/
xmlXIncludeCtxtPtr
xmlXIncludeNewContext(xmlDocPtr doc) {
xmlXIncludeCtxtPtr ret;
if (doc == NULL)
return(NULL);
ret = (xmlXIncludeCtxtPtr) xmlMalloc(sizeof(xmlXIncludeCtxt));
if (ret == NULL)
return(NULL);
memset(ret, 0, sizeof(xmlXIncludeCtxt));
ret->doc = doc;
ret->incNr = 0;
ret->incMax = 0;
ret->incTab = NULL;
ret->repTab = NULL;
ret->docNr = 0;
ret->docMax = 0;
ret->docTab = NULL;
ret->urlTab = NULL;
return(ret);
}
/**
* xmlXIncludeFreeContext:
* @ctxt: the XInclude context
*
* Free an XInclude context
*/
void
xmlXIncludeFreeContext(xmlXIncludeCtxtPtr ctxt) {
if (ctxt == NULL)
return;
if (ctxt->incTab != NULL)
xmlFree(ctxt->incTab);
if (ctxt->repTab != NULL)
xmlFree(ctxt->repTab);
memset(ctxt, 0xeb, sizeof(xmlXIncludeCtxt));
xmlFree(ctxt);
}
/************************************************************************
* *
* XInclude I/O handling *
* *
************************************************************************/
/**
* xmlXIncludeLoadDoc:
* @ctxt: the XInclude context
* @url: the associated URL
* @nr: the xinclude node number
*
* Load the document, and store the result in the XInclude context
*/
void
xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int nr) {
xmlDocPtr doc;
xmlURIPtr uri;
xmlChar *URL;
int i;
/*
* Check the URL and remove any fragment identifier
*/
uri = xmlParseURI((const char *)url);
if (uri == NULL) {
xmlGenericError(xmlGenericErrorContext,
"XInclude: invalid value URI %s\n", url);
return;
}
if (uri->fragment != NULL) {
xmlFree(uri->fragment);
uri->fragment = NULL; /* TODO: kkep it for later processing */
}
URL = xmlSaveUri(uri);
xmlFreeURI(uri);
if (URL == NULL) {
xmlGenericError(xmlGenericErrorContext,
"XInclude: invalid value URI %s\n", url);
return;
}
/*
* Handling of references to the local document are done
* directly through ctxt->doc.
*/
if (URL[0] == 0) {
xmlFree(URL);
return;
}
/*
* Prevent reloading twice the document.
*/
for (i = 0; i < ctxt->docNr; i++) {
if (xmlStrEqual(URL, ctxt->urlTab[i])) {
doc = ctxt->docTab[i];
goto loaded;
}
}
/*
* Load it.
*/
doc = xmlParseFile((const char *)URL);
if (doc == NULL) {
xmlGenericError(xmlGenericErrorContext,
"XInclude: could not load %s\n", URL);
xmlFree(URL);
return;
}
xmlXIncludeAddDoc(ctxt, doc, URL);
loaded:
/*
* Add the top children list as the replacement copy.
*/
ctxt->repTab[nr] = xmlCopyNodeList(doc->children);
xmlFree(URL);
}
/**
* xmlXIncludeLoadTxt:
* @ctxt: the XInclude context
* @url: the associated URL
* @nr: the xinclude node number
*
* Load the content, and store the result in the XInclude context
*/
void
xmlXIncludeLoadTxt(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int nr) {
xmlParserInputBufferPtr buf;
xmlNodePtr node;
xmlURIPtr uri;
xmlChar *URL;
int i;
/*
* Check the URL and remove any fragment identifier
*/
uri = xmlParseURI((const char *)url);
if (uri == NULL) {
xmlGenericError(xmlGenericErrorContext,
"XInclude: invalid value URI %s\n", url);
return;
}
if (uri->fragment != NULL) {
xmlFreeURI(uri);
xmlGenericError(xmlGenericErrorContext,
"XInclude: fragment identifier forbidden for text\n");
return;
}
URL = xmlSaveUri(uri);
xmlFreeURI(uri);
if (URL == NULL) {
xmlGenericError(xmlGenericErrorContext,
"XInclude: invalid value URI %s\n", url);
return;
}
/*
* Handling of references to the local document are done
* directly through ctxt->doc.
*/
if (URL[0] == 0) {
xmlGenericError(xmlGenericErrorContext,
"XInclude: text serialization of document not available\n");
xmlFree(URL);
return;
}
/*
* Prevent reloading twice the document.
*/
for (i = 0; i < ctxt->txtNr; i++) {
if (xmlStrEqual(URL, ctxt->txturlTab[i])) {
node = xmlCopyNode(ctxt->txtTab[i], 1);
goto loaded;
}
}
/*
* Load it.
* Issue 62: how to detect the encoding
*/
buf = xmlParserInputBufferCreateFilename((const char *)URL, 0);
if (buf == NULL) {
xmlGenericError(xmlGenericErrorContext,
"XInclude: could not load %s\n", URL);
xmlFree(URL);
return;
}
node = xmlNewText(NULL);
/*
* Scan all chars from the resource and add the to the node
*/
while (xmlParserInputBufferRead(buf, 128) > 0) {
int len;
const xmlChar *content;
content = xmlBufferContent(buf->buffer);
len = xmlBufferLength(buf->buffer);
for (i = 0;i < len; i++) {
/*
* TODO: if the encoding issue is solved, scan UTF8 chars instead
*/
if (!IS_CHAR(content[i])) {
xmlGenericError(xmlGenericErrorContext,
"XInclude: %s contains invalid char %d\n", URL, content[i]);
} else {
xmlNodeAddContentLen(node, &content[i], 1);
}
}
xmlBufferShrink(buf->buffer, len);
}
xmlFreeParserInputBuffer(buf);
xmlXIncludeAddTxt(ctxt, node, URL);
loaded:
/*
* Add the element as the replacement copy.
*/
ctxt->repTab[nr] = node;
xmlFree(URL);
}
/************************************************************************
* *
* XInclude Processing *
* *
************************************************************************/
/**
* xmlXIncludePreProcessNode:
* @ctxt: an XInclude context
* @node: an XInclude node
*
* Implement the infoset replacement lookup on the XML element @node
*
* Returns the result list or NULL in case of error
*/
xmlNodePtr
xmlXIncludePreProcessNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
xmlXIncludeAddNode(ctxt, node);
return(0);
}
/**
* xmlXIncludeLoadNode:
* @ctxt: an XInclude context
* @nr: the node number
*
* Find and load the infoset replacement for the given node.
*
* Returns 0 if substition succeeded, -1 if some processing failed
*/
int
xmlXIncludeLoadNode(xmlXIncludeCtxtPtr ctxt, int nr) {
xmlNodePtr cur;
xmlChar *href;
xmlChar *parse;
xmlChar *base;
xmlChar *URI;
int xml = 1; /* default Issue 64 */
if (ctxt == NULL)
return(-1);
if ((nr < 0) || (nr >= ctxt->incNr))
return(-1);
cur = ctxt->incTab[nr];
if (cur == NULL)
return(-1);
#ifdef DEBUG_XINCLUDE
xmlDebugDumpNode(stdout, cur, 0);
#endif
/*
* read the attributes
*/
href = xmlGetNsProp(cur, XINCLUDE_NS, XINCLUDE_HREF);
if (href == NULL) {
href = xmlGetProp(cur, XINCLUDE_HREF);
if (href == NULL) {
xmlGenericError(xmlGenericErrorContext, "XInclude: no href\n");
return(-1);
}
}
parse = xmlGetNsProp(cur, XINCLUDE_NS, XINCLUDE_PARSE);
if (parse == NULL) {
parse = xmlGetProp(cur, XINCLUDE_PARSE);
}
if (parse != NULL) {
if (xmlStrEqual(parse, XINCLUDE_PARSE_XML))
xml = 1;
else if (xmlStrEqual(parse, XINCLUDE_PARSE_TEXT))
xml = 0;
else {
xmlGenericError(xmlGenericErrorContext,
"XInclude: invalid value %s for %s\n",
parse, XINCLUDE_PARSE);
if (href != NULL)
xmlFree(href);
if (parse != NULL)
xmlFree(parse);
return(-1);
}
}
/*
* compute the URI
*/
base = xmlNodeGetBase(ctxt->doc, cur);
URI = xmlBuildURI(href, base);
if (URI == NULL) {
xmlChar *escbase;
xmlChar *eschref;
/*
* Some escapeing may be needed
*/
escbase = xmlURIEscape(base);
eschref = xmlURIEscape(href);
URI = xmlBuildURI(eschref, escbase);
if (escbase != NULL)
xmlFree(escbase);
if (eschref != NULL)
xmlFree(eschref);
}
if (URI == NULL) {
xmlGenericError(xmlGenericErrorContext, "XInclude: failed build URL\n");
if (parse != NULL)
xmlFree(parse);
if (href != NULL)
xmlFree(href);
if (base != NULL)
xmlFree(base);
return(-1);
}
#ifdef DEBUG_XINCLUDE
xmlGenericError(xmlGenericErrorContext, "parse: %s\n",
xml ? "xml": "text");
xmlGenericError(xmlGenericErrorContext, "URI: %s\n", URI);
#endif
/*
* Cleanup
*/
if (xml) {
xmlXIncludeLoadDoc(ctxt, URI, nr);
/* xmlXIncludeGetFragment(ctxt, cur, URI); */
} else {
xmlXIncludeLoadTxt(ctxt, URI, nr);
}
/*
* Cleanup
*/
if (URI != NULL)
xmlFree(URI);
if (parse != NULL)
xmlFree(parse);
if (href != NULL)
xmlFree(href);
if (base != NULL)
xmlFree(base);
return(0);
}
/**
* xmlXIncludeIncludeNode:
* @ctxt: an XInclude context
* @nr: the node number
*
* Inplement the infoset replacement for the given node
*
* Returns 0 if substition succeeded, -1 if some processing failed
*/
int
xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) {
xmlNodePtr cur, end, list;
if (ctxt == NULL)
return(-1);
if ((nr < 0) || (nr >= ctxt->incNr))
return(-1);
cur = ctxt->incTab[nr];
if (cur == NULL)
return(-1);
/*
* Change the current node as an XInclude start one, and add an
* entity end one
*/
cur->type = XML_XINCLUDE_START;
end = xmlNewNode(cur->ns, cur->name);
if (end == NULL) {
xmlGenericError(xmlGenericErrorContext,
"XInclude: failed to build node\n");
return(-1);
}
end->type = XML_XINCLUDE_END;
xmlAddNextSibling(cur, end);
/*
* Add the list of nodes
*/
list = ctxt->repTab[nr];
ctxt->repTab[nr] = NULL;
while (list != NULL) {
cur = list;
list = list->next;
xmlAddPrevSibling(end, cur);
}
return(0);
}
/**
* xmlXIncludeTestNode:
* @doc: an XML document
* @node: an XInclude node
*
* test if the node is an XInclude node
*
* Returns 1 true, 0 otherwise
*/
int
xmlXIncludeTestNode(xmlDocPtr doc, xmlNodePtr node) {
if (node == NULL)
return(0);
if (node->ns == NULL)
return(0);
if ((xmlStrEqual(node->name, XINCLUDE_NODE)) &&
(xmlStrEqual(node->ns->href, XINCLUDE_NS))) return(1);
return(0);
}
/**
* xmlXIncludeProcess:
* @doc: an XML document
*
* Implement the XInclude substitution on the XML document @doc
*
* Returns 0 if no substition were done, -1 if some processing failed
* or the number of substitutions done.
*/
int
xmlXIncludeProcess(xmlDocPtr doc) {
xmlXIncludeCtxtPtr ctxt;
xmlNodePtr cur;
int ret = 0;
int i;
if (doc == NULL)
return(-1);
ctxt = xmlXIncludeNewContext(doc);
if (ctxt == NULL)
return(-1);
/*
* First phase: lookup the elements in the document
*/
cur = xmlDocGetRootElement(doc);
if (xmlXIncludeTestNode(doc, cur))
xmlXIncludePreProcessNode(ctxt, cur);
while (cur != NULL) {
/* TODO: need to work on entities -> stack */
if ((cur->children != NULL) &&
(cur->children->type != XML_ENTITY_DECL)) {
cur = cur->children;
if (xmlXIncludeTestNode(doc, cur))
xmlXIncludePreProcessNode(ctxt, cur);
} else if (cur->next != NULL) {
cur = cur->next;
if (xmlXIncludeTestNode(doc, cur))
xmlXIncludePreProcessNode(ctxt, cur);
} else {
do {
cur = cur->parent;
if (cur == NULL) break; /* do */
if (cur->next != NULL) {
cur = cur->next;
if (xmlXIncludeTestNode(doc, cur))
xmlXIncludePreProcessNode(ctxt, cur);
break; /* do */
}
} while (cur != NULL);
}
}
/*
* Second Phase : collect the infosets fragments
*/
for (i = 0;i < ctxt->incNr; i++) {
xmlXIncludeLoadNode(ctxt, i);
}
/*
* Third phase: extend the original document infoset.
*/
for (i = 0;i < ctxt->incNr; i++) {
xmlXIncludeIncludeNode(ctxt, i);
}
/*
* Cleanup
*/
xmlXIncludeFreeContext(ctxt);
return(ret);
}
#else /* !LIBXML_XINCLUDE_ENABLED */
#endif

26
xinclude.h Normal file
View File

@ -0,0 +1,26 @@
/*
* xinclude.c : API to handle XInclude processing
*
* World Wide Web Consortium Working Draft 26 October 2000
* http://www.w3.org/TR/2000/WD-xinclude-20001026
*
* See Copyright for the status of this software.
*
* Daniel.Veillard@w3.org
*/
#ifndef __XML_XINCLUDE_H__
#define __XML_XINCLUDE_H__
#include <libxml/tree.h>
#ifdef __cplusplus
extern "C" {
#endif
int xmlXIncludeProcess (xmlDocPtr doc);
#ifdef __cplusplus
}
#endif
#endif /* __XML_XINCLUDE_H__ */

View File

@ -55,6 +55,9 @@
#include <libxml/xpath.h>
#include <libxml/debugXML.h>
#include <libxml/xmlerror.h>
#ifdef LIBXML_XINCLUDE_ENABLED
#include <libxml/xinclude.h>
#endif
#ifdef LIBXML_DEBUG_ENABLED
static int debug = 0;
@ -81,6 +84,9 @@ static int memory = 0;
static int noblanks = 0;
static int testIO = 0;
static char *encoding = NULL;
#ifdef LIBXML_XINCLUDE_ENABLED
static int xinclude = 0;
#endif
extern int xmlDoValidityCheckingDefaultValue;
extern int xmlGetWarningsDefaultValue;
@ -497,10 +503,14 @@ void parseAndPrintFile(char *filename) {
/*
* If we don't have a document we might as well give up. Do we
* want an error message here? <sven@zen.org> */
if (doc == NULL)
{
if (doc == NULL) {
return;
}
}
#ifdef LIBXML_XINCLUDE_ENABLED
if (xinclude)
xmlXIncludeProcess(doc);
#endif
#ifdef LIBXML_DEBUG_ENABLED
/*
@ -667,6 +677,11 @@ int main(int argc, char **argv) {
else if ((!strcmp(argv[i], "-testIO")) ||
(!strcmp(argv[i], "--testIO")))
testIO++;
#ifdef LIBXML_XINCLUDE_ENABLED
else if ((!strcmp(argv[i], "-xinclude")) ||
(!strcmp(argv[i], "--xinclude")))
xinclude++;
#endif
else if ((!strcmp(argv[i], "-compress")) ||
(!strcmp(argv[i], "--compress"))) {
compress++;
@ -773,6 +788,9 @@ int main(int argc, char **argv) {
printf("\t--noblanks : drop (ignorable?) blanks spaces\n");
printf("\t--testIO : test user I/O support\n");
printf("\t--encode encoding : output in the given encoding\n");
#ifdef LIBXML_XINCLUDE_ENABLED
printf("\t--xinclude : do XInclude processing\n");
#endif
}
xmlCleanupParser();
xmlMemoryDump();

View File

@ -77,6 +77,15 @@ extern void xmlCheckVersion(int version);
#define LIBXML_XPTR_DISABLED
#endif
/*
* Whether XInclude is configured in
*/
#if @WITH_XINCLUDE@
#define LIBXML_XINCLUDE_ENABLED
#else
#define LIBXML_XINCLUDE_DISABLED
#endif
/*
* Whether iconv support is available
*/

150
xpath.c
View File

@ -597,20 +597,51 @@ xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) {
*/
xmlNodeSetPtr
xmlXPathNodeSetMerge(xmlNodeSetPtr val1, xmlNodeSetPtr val2) {
int i;
int i, j, initNr;
if (val2 == NULL) return(val1);
if (val1 == NULL) {
val1 = xmlXPathNodeSetCreate(NULL);
}
/*
* !!!!! this can be optimized a lot, knowing that both
* val1 and val2 already have unicity of their values.
*/
initNr = val1->nodeNr;
for (i = 0;i < val2->nodeNr;i++)
xmlXPathNodeSetAdd(val1, val2->nodeTab[i]);
for (i = 0;i < val2->nodeNr;i++) {
/*
* check against doublons
*/
for (j = 0; j < initNr; j++)
if (val1->nodeTab[j] == val2->nodeTab[i]) continue;
/*
* grow the nodeTab if needed
*/
if (val1->nodeMax == 0) {
val1->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
sizeof(xmlNodePtr));
if (val1->nodeTab == NULL) {
xmlGenericError(xmlGenericErrorContext,
"xmlXPathNodeSetMerge: out of memory\n");
return(NULL);
}
memset(val1->nodeTab, 0 ,
XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
val1->nodeMax = XML_NODESET_DEFAULT;
} else if (val1->nodeNr == val1->nodeMax) {
xmlNodePtr *temp;
val1->nodeMax *= 2;
temp = (xmlNodePtr *) xmlRealloc(val1->nodeTab, val1->nodeMax *
sizeof(xmlNodePtr));
if (temp == NULL) {
xmlGenericError(xmlGenericErrorContext,
"xmlXPathNodeSetMerge: out of memory\n");
return(NULL);
}
val1->nodeTab = temp;
}
val1->nodeTab[val1->nodeNr++] = val2->nodeTab[i];
}
return(val1);
}
@ -1922,12 +1953,12 @@ typedef xmlNodePtr (*xmlXPathTraversalFunction)
(xmlXPathParserContextPtr ctxt, xmlNodePtr cur);
/**
* mlXPathNextSelf:
* xmlXPathNextSelf:
* @ctxt: the XPath Parser context
* @cur: the current node in the traversal
*
* Traversal function for the "self" direction
* he self axis contains just the context node itself
* The self axis contains just the context node itself
*
* Returns the next element following that axis
*/
@ -1939,7 +1970,7 @@ xmlXPathNextSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
}
/**
* mlXPathNextChild:
* xmlXPathNextChild:
* @ctxt: the XPath Parser context
* @cur: the current node in the traversal
*
@ -1976,6 +2007,8 @@ xmlXPathNextChild(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
case XML_ENTITY_DECL:
case XML_ATTRIBUTE_NODE:
case XML_NAMESPACE_DECL:
case XML_XINCLUDE_START:
case XML_XINCLUDE_END:
return(NULL);
}
return(NULL);
@ -1987,7 +2020,7 @@ xmlXPathNextChild(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
}
/**
* mlXPathNextDescendant:
* xmlXPathNextDescendant:
* @ctxt: the XPath Parser context
* @cur: the current node in the traversal
*
@ -2002,7 +2035,8 @@ xmlXPathNextDescendant(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
if (cur == NULL) {
if (ctxt->context->node == NULL)
return(NULL);
if (ctxt->context->node->type == XML_ATTRIBUTE_NODE)
if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
(ctxt->context->node->type == XML_NAMESPACE_DECL))
return(NULL);
if (ctxt->context->node == (xmlNodePtr) ctxt->context->doc)
@ -2030,7 +2064,7 @@ xmlXPathNextDescendant(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
}
/**
* mlXPathNextDescendantOrSelf:
* xmlXPathNextDescendantOrSelf:
* @ctxt: the XPath Parser context
* @cur: the current node in the traversal
*
@ -2047,7 +2081,8 @@ xmlXPathNextDescendantOrSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
if (cur == NULL) {
if (ctxt->context->node == NULL)
return(NULL);
if (ctxt->context->node->type == XML_ATTRIBUTE_NODE)
if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
(ctxt->context->node->type == XML_NAMESPACE_DECL))
return(NULL);
return(ctxt->context->node);
}
@ -2086,6 +2121,8 @@ xmlXPathNextParent(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
case XML_DTD_NODE:
case XML_ELEMENT_DECL:
case XML_ATTRIBUTE_DECL:
case XML_XINCLUDE_START:
case XML_XINCLUDE_END:
case XML_ENTITY_DECL:
if (ctxt->context->node->parent == NULL)
return((xmlNodePtr) ctxt->context->doc);
@ -2151,6 +2188,8 @@ xmlXPathNextAncestor(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
case XML_ATTRIBUTE_DECL:
case XML_ENTITY_DECL:
case XML_NOTATION_NODE:
case XML_XINCLUDE_START:
case XML_XINCLUDE_END:
if (ctxt->context->node->parent == NULL)
return((xmlNodePtr) ctxt->context->doc);
return(ctxt->context->node->parent);
@ -2194,6 +2233,8 @@ xmlXPathNextAncestor(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
case XML_ELEMENT_DECL:
case XML_ATTRIBUTE_DECL:
case XML_ENTITY_DECL:
case XML_XINCLUDE_START:
case XML_XINCLUDE_END:
return(cur->parent);
case XML_ATTRIBUTE_NODE: {
xmlAttrPtr att = (xmlAttrPtr) ctxt->context->node;
@ -2252,6 +2293,9 @@ xmlXPathNextAncestorOrSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
*/
xmlNodePtr
xmlXPathNextFollowingSibling(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
(ctxt->context->node->type == XML_NAMESPACE_DECL))
return(NULL);
if (cur == (xmlNodePtr) ctxt->context->doc)
return(NULL);
if (cur == NULL)
@ -2273,6 +2317,9 @@ xmlXPathNextFollowingSibling(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
*/
xmlNodePtr
xmlXPathNextPrecedingSibling(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
(ctxt->context->node->type == XML_NAMESPACE_DECL))
return(NULL);
if (cur == (xmlNodePtr) ctxt->context->doc)
return(NULL);
if (cur == NULL)
@ -2303,7 +2350,7 @@ xmlXPathNextFollowing(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
do {
cur = cur->parent;
if (cur == NULL) return(NULL);
if (cur == ctxt->context->doc->children) return(NULL); /* !!!!!?!? */
if (cur == (xmlNodePtr) ctxt->context->doc) return(NULL);
if (cur->next != NULL) return(cur->next);
} while (cur != NULL);
return(cur);
@ -2320,13 +2367,18 @@ xmlXPathNextFollowing(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
*/
static int
xmlXPathIsAncestor(xmlNodePtr ancestor, xmlNodePtr node) {
xmlNodePtr tmp ;
if (ancestor == NULL || node == NULL) return 0 ;
for (tmp = node ; tmp->parent != NULL ; tmp = tmp->parent) {
if (tmp->parent == ancestor)
return 1 ;
if ((ancestor == NULL) || (node == NULL)) return(0);
/* nodes need to be in the same document */
if (ancestor->doc != node->doc) return(0);
/* avoid searching if ancestor or node is the root node */
if (ancestor == (xmlNodePtr) node->doc) return(1);
if (node == (xmlNodePtr) ancestor->doc) return(0);
while (node->parent != NULL) {
if (node->parent == ancestor)
return(1);
node = node->parent;
}
return 0 ;
return(0);
}
/**
@ -2372,8 +2424,9 @@ xmlXPathNextPreceding(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
*
* Returns the next element following that axis
*/
xmlNsPtr
xmlXPathNextNamespace(xmlXPathParserContextPtr ctxt, xmlAttrPtr cur) {
xmlNodePtr
xmlXPathNextNamespace(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
if (ctxt->context->node->type != XML_ELEMENT_NODE) return(NULL);
if ((cur == NULL) || (ctxt->context->namespaces == NULL)) {
if (ctxt->context->namespaces != NULL)
xmlFree(ctxt->context->namespaces);
@ -2382,7 +2435,7 @@ xmlXPathNextNamespace(xmlXPathParserContextPtr ctxt, xmlAttrPtr cur) {
if (ctxt->context->namespaces == NULL) return(NULL);
ctxt->context->nsNr = 0;
}
return(ctxt->context->namespaces[ctxt->context->nsNr++]);
return((xmlNodePtr)ctxt->context->namespaces[ctxt->context->nsNr++]);
}
/**
@ -2395,14 +2448,15 @@ xmlXPathNextNamespace(xmlXPathParserContextPtr ctxt, xmlAttrPtr cur) {
*
* Returns the next element following that axis
*/
xmlAttrPtr
xmlXPathNextAttribute(xmlXPathParserContextPtr ctxt, xmlAttrPtr cur) {
xmlNodePtr
xmlXPathNextAttribute(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
if (ctxt->context->node->type != XML_ELEMENT_NODE) return(NULL);
if (cur == NULL) {
if (ctxt->context->node == (xmlNodePtr) ctxt->context->doc)
return(NULL);
return(ctxt->context->node->properties);
return((xmlNodePtr)ctxt->context->node->properties);
}
return(cur->next);
return((xmlNodePtr)cur->next);
}
/************************************************************************
@ -2483,7 +2537,7 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt, xmlXPathAxisVal axis,
xmlGenericError(xmlGenericErrorContext,
"axis 'attributes' ");
#endif
next = (xmlXPathTraversalFunction) xmlXPathNextAttribute; break;
next = xmlXPathNextAttribute; break;
break;
case AXIS_CHILD:
#ifdef DEBUG_STEP
@ -2637,17 +2691,33 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt, xmlXPathAxisVal axis,
}
break;
case NODE_TEST_ALL:
if ((cur->type == XML_ELEMENT_NODE) ||
(cur->type == XML_DOCUMENT_NODE) ||
(cur->type == XML_HTML_DOCUMENT_NODE)) {
if (axis == AXIS_ATTRIBUTE) {
if (cur->type == XML_ATTRIBUTE_NODE) {
#ifdef DEBUG_STEP
n++;
n++;
#endif
xmlXPathNodeSetAdd(ret, cur);
xmlXPathNodeSetAdd(ret, cur);
}
} else if (axis == AXIS_NAMESPACE) {
if (cur->type == XML_NAMESPACE_DECL) {
#ifdef DEBUG_STEP
n++;
#endif
xmlXPathNodeSetAdd(ret, cur);
}
} else {
if ((cur->type == XML_ELEMENT_NODE) ||
(cur->type == XML_DOCUMENT_NODE) ||
(cur->type == XML_HTML_DOCUMENT_NODE)) {
#ifdef DEBUG_STEP
n++;
#endif
xmlXPathNodeSetAdd(ret, cur);
}
}
break;
case NODE_TEST_NS: {
TODO /* namespace search */
TODO;
break;
}
case NODE_TEST_NAME:
@ -2673,6 +2743,10 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt, xmlXPathAxisVal axis,
}
break;
}
case XML_NAMESPACE_DECL: {
TODO;
break;
}
default:
break;
}
@ -2720,6 +2794,7 @@ xmlXPathRoot(xmlXPathParserContextPtr ctxt) {
* @ctxt: the XPath Parser context
*
* Implement the last() XPath function
* number last()
* The last function returns the number of nodes in the context node list.
*/
void
@ -2913,6 +2988,10 @@ xmlXPathLocalNameFunction(xmlXPathParserContextPtr ctxt, int nargs) {
valuePush(ctxt,
xmlXPathNewString(cur->nodesetval->nodeTab[i]->name));
break;
case XML_NAMESPACE_DECL:
valuePush(ctxt, xmlXPathNewString(
((xmlNsPtr)cur->nodesetval->nodeTab[i])->prefix));
break;
default:
valuePush(ctxt, xmlXPathNewCString(""));
}
@ -4572,6 +4651,7 @@ xmlXPathEvalUnionExpr(xmlXPathParserContextPtr ctxt) {
obj2 = valuePop(ctxt);
obj1->nodesetval = xmlXPathNodeSetMerge(obj1->nodesetval,
obj2->nodesetval);
valuePush(ctxt, obj1);
xmlXPathFreeObject(obj2);
SKIP_BLANKS;
}

View File

@ -25,6 +25,7 @@
*/
#include <stdio.h>
#include <string.h>
#include <libxml/xpointer.h>
#include <libxml/xmlmemory.h>
#include <libxml/parserInternals.h>
@ -1711,8 +1712,13 @@ xmlXPtrInsideRange(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr loc) {
if (node->content == NULL) {
return(xmlXPtrNewRange(node, 0, node, 0));
} else {
#ifndef XML_USE_BUFFER_CONTENT
return(xmlXPtrNewRange(node, 0, node,
xmlStrlen(node->content)));
#else
return(xmlXPtrNewRange(node, 0, node,
xmlBufferLength(node->content)));
#endif
}
}
case XML_ATTRIBUTE_NODE:
@ -1743,8 +1749,13 @@ xmlXPtrInsideRange(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr loc) {
if (node->content == NULL) {
return(xmlXPtrNewRange(node, 0, node, 0));
} else {
#ifndef XML_USE_BUFFER_CONTENT
return(xmlXPtrNewRange(node, 0, node,
xmlStrlen(node->content)));
#else
return(xmlXPtrNewRange(node, 0, node,
xmlBufferLength(node->content)));
#endif
}
}
case XML_ATTRIBUTE_NODE:
@ -2010,7 +2021,11 @@ xmlXPtrAdvanceChar(xmlNodePtr *node, int *index, int bytes) {
*/
len = 0;
if (cur->content != NULL) {
#ifndef XML_USE_BUFFER_CONTENT
len = xmlStrlen(cur->content);
#else
len = xmlBufferLength(cur->content);
#endif
}
if (pos > len) {
/* Strange, the index in the text node is greater than it's len */
@ -2072,9 +2087,18 @@ xmlXPtrMatchString(const xmlChar *string, xmlNodePtr start, int startindex,
if ((cur == *end) && (pos + stringlen > *endindex))
return(0);
if (cur->content != NULL) {
#ifndef XML_USE_BUFFER_CONTENT
len = xmlStrlen(cur->content);
#else
len = xmlBufferLength(cur->content);
#endif
if (len >= pos + stringlen) {
#ifndef XML_USE_BUFFER_CONTENT
match = (!xmlStrncmp(&cur->content[pos], string, stringlen));
#else
len = (!xmlStrncmp(&xmlBufferContent(cur->content)[pos],
string, stringlen));
#endif
if (match) {
#ifdef DEBUG_RANGES
xmlGenericError(xmlGenericErrorContext,
@ -2091,7 +2115,12 @@ xmlXPtrMatchString(const xmlChar *string, xmlNodePtr start, int startindex,
}
} else {
int sub = len - pos;
#ifndef XML_USE_BUFFER_CONTENT
match = (!xmlStrncmp(&cur->content[pos], string, sub));
#else
len = (!xmlStrncmp(&xmlBufferContent(cur->content)[pos],
string, sub));
#endif
if (match) {
#ifdef DEBUG_RANGES
xmlGenericError(xmlGenericErrorContext,
@ -2156,12 +2185,21 @@ xmlXPtrSearchString(const xmlChar *string, xmlNodePtr *start, int *startindex,
while (cur != NULL) {
if (cur->content != NULL) {
#ifndef XML_USE_BUFFER_CONTENT
len = xmlStrlen(cur->content);
#else
len = xmlBufferLength(cur->content);
#endif
while (pos <= len) {
if (first != 0) {
#ifndef XML_USE_BUFFER_CONTENT
str = xmlStrchr(&cur->content[pos], first);
#else
str = xmlStrchr(&xmlBufferContent(cur->content)[pos],
first);
#endif
if (str != NULL) {
pos = (str - cur->content);
pos = (str - (xmlChar *)(cur->content));
#ifdef DEBUG_RANGES
xmlGenericError(xmlGenericErrorContext,
"found '%c' at index %d of ->",
@ -2244,7 +2282,11 @@ xmlXPtrGetLastChar(xmlNodePtr *node, int *index) {
if (cur->last != NULL)
cur = cur->last;
else if (cur->content != NULL) {
#ifndef XML_USE_BUFFER_CONTENT
len = xmlStrlen(cur->content);
#else
len = xmlBufferLength(cur->content);
#endif
break;
}
}
@ -2459,7 +2501,7 @@ xmlXPtrStringRangeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
xmlXPtrNewRange(start, startindex,
rend, rindex));
}
} else if (num <= 0) {
} else if ((number != NULL) && (num <= 0)) {
xmlXPtrLocationSetAdd(newset,
xmlXPtrNewRange(start, startindex,
start, startindex));