mirror of
https://github.com/GNOME/libxml2.git
synced 2025-04-06 19:20:23 +08:00
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:
parent
a4964b7500
commit
9e8bfae59a
11
ChangeLog
11
ChangeLog
@ -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
|
||||
|
@ -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;
|
||||
|
@ -34,6 +34,7 @@ libxml_la_SOURCES = \
|
||||
debugXML.c \
|
||||
xpath.c \
|
||||
xpointer.c \
|
||||
xinclude.c \
|
||||
nanohttp.c \
|
||||
nanoftp.c
|
||||
|
||||
|
13
configure.in
13
configure.in
@ -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
|
||||
|
11
debugXML.c
11
debugXML.c
@ -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
1
hash.c
@ -17,6 +17,7 @@
|
||||
* Author: bjorn.reese@systematic.dk
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <libxml/hash.h>
|
||||
#include <libxml/xmlmemory.h>
|
||||
#include <libxml/parser.h>
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
26
include/libxml/xinclude.h
Normal 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__ */
|
@ -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
|
||||
*/
|
||||
|
@ -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
218
tree.c
@ -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
6
tree.h
@ -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
353
uri.c
@ -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
1
uri.h
@ -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
|
||||
|
3
valid.c
3
valid.c
@ -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
737
xinclude.c
Normal 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
26
xinclude.h
Normal 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__ */
|
24
xmllint.c
24
xmllint.c
@ -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();
|
||||
|
@ -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
150
xpath.c
@ -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;
|
||||
}
|
||||
|
46
xpointer.c
46
xpointer.c
@ -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));
|
||||
|
Loading…
x
Reference in New Issue
Block a user