mirror of
https://gitlab.gnome.org/GNOME/libxslt
synced 2025-11-02 13:33:20 +03:00
Infrastructure to store extra data in source nodes
Provide a mechanism to store bit flags in nodes from the source document. This will later be used to store key and id status. Provide a function to find the psvi member of a node. Revert any changes to the source document after the transformation.
This commit is contained in:
@@ -5746,6 +5746,37 @@ xsltCountKeys(xsltTransformContextPtr ctxt)
|
||||
return(ctxt->nbKeys);
|
||||
}
|
||||
|
||||
/**
|
||||
* xsltCleanupSourceDoc:
|
||||
* @doc: Document
|
||||
*
|
||||
* Resets source node flags and ids stored in 'psvi' member.
|
||||
*/
|
||||
static void
|
||||
xsltCleanupSourceDoc(xmlDocPtr doc) {
|
||||
xmlNodePtr cur = (xmlNodePtr) doc;
|
||||
void **psviPtr;
|
||||
|
||||
while (1) {
|
||||
xsltClearSourceNodeFlags(cur, XSLT_SOURCE_NODE_MASK);
|
||||
psviPtr = xsltGetPSVIPtr(cur);
|
||||
if (psviPtr)
|
||||
*psviPtr = NULL;
|
||||
|
||||
if (cur->children != NULL && cur->type != XML_ENTITY_REF_NODE) {
|
||||
cur = cur->children;
|
||||
} else {
|
||||
while (cur->next == NULL) {
|
||||
cur = cur->parent;
|
||||
if (cur == (xmlNodePtr) doc)
|
||||
return;
|
||||
}
|
||||
|
||||
cur = cur->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* xsltApplyStylesheetInternal:
|
||||
* @style: a parsed XSLT stylesheet
|
||||
@@ -6144,6 +6175,9 @@ xsltApplyStylesheetInternal(xsltStylesheetPtr style, xmlDocPtr doc,
|
||||
printf("# Reused variables : %d\n", ctxt->cache->dbgReusedVars);
|
||||
#endif
|
||||
|
||||
if (ctxt->sourceDocDirty)
|
||||
xsltCleanupSourceDoc(doc);
|
||||
|
||||
if ((ctxt != NULL) && (userCtxt == NULL))
|
||||
xsltFreeTransformContext(ctxt);
|
||||
|
||||
|
||||
@@ -1786,6 +1786,7 @@ struct _xsltTransformContext {
|
||||
int maxTemplateVars;
|
||||
unsigned long opLimit;
|
||||
unsigned long opCount;
|
||||
int sourceDocDirty;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -1834,6 +1834,141 @@ xsltSaveResultToString(xmlChar **doc_txt_ptr, int * doc_txt_len,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* xsltGetSourceNodeFlags:
|
||||
* @node: Node from source document
|
||||
*
|
||||
* Returns the flags for a source node.
|
||||
*/
|
||||
int
|
||||
xsltGetSourceNodeFlags(xmlNodePtr node) {
|
||||
/*
|
||||
* Squeeze the bit flags into the upper bits of
|
||||
*
|
||||
* - 'int properties' member in struct _xmlDoc
|
||||
* - 'xmlAttributeType atype' member in struct _xmlAttr
|
||||
* - 'unsigned short extra' member in struct _xmlNode
|
||||
*/
|
||||
switch (node->type) {
|
||||
case XML_DOCUMENT_NODE:
|
||||
case XML_HTML_DOCUMENT_NODE:
|
||||
return ((xmlDocPtr) node)->properties >> 27;
|
||||
|
||||
case XML_ATTRIBUTE_NODE:
|
||||
return ((xmlAttrPtr) node)->atype >> 27;
|
||||
|
||||
case XML_ELEMENT_NODE:
|
||||
case XML_TEXT_NODE:
|
||||
case XML_CDATA_SECTION_NODE:
|
||||
case XML_PI_NODE:
|
||||
case XML_COMMENT_NODE:
|
||||
return node->extra >> 12;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* xsltSetSourceNodeFlags:
|
||||
* @node: Node from source document
|
||||
* @flags: Flags
|
||||
*
|
||||
* Sets the specified flags to 1.
|
||||
*
|
||||
* Returns 0 on success, -1 on error.
|
||||
*/
|
||||
int
|
||||
xsltSetSourceNodeFlags(xsltTransformContextPtr ctxt, xmlNodePtr node,
|
||||
int flags) {
|
||||
if (node->doc == ctxt->initialContextDoc)
|
||||
ctxt->sourceDocDirty = 1;
|
||||
|
||||
switch (node->type) {
|
||||
case XML_DOCUMENT_NODE:
|
||||
case XML_HTML_DOCUMENT_NODE:
|
||||
((xmlDocPtr) node)->properties |= flags << 27;
|
||||
return 0;
|
||||
|
||||
case XML_ATTRIBUTE_NODE:
|
||||
((xmlAttrPtr) node)->atype |= flags << 27;
|
||||
return 0;
|
||||
|
||||
case XML_ELEMENT_NODE:
|
||||
case XML_TEXT_NODE:
|
||||
case XML_CDATA_SECTION_NODE:
|
||||
case XML_PI_NODE:
|
||||
case XML_COMMENT_NODE:
|
||||
node->extra |= flags << 12;
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* xsltClearSourceNodeFlags:
|
||||
* @node: Node from source document
|
||||
* @flags: Flags
|
||||
*
|
||||
* Sets the specified flags to 0.
|
||||
*
|
||||
* Returns 0 on success, -1 on error.
|
||||
*/
|
||||
int
|
||||
xsltClearSourceNodeFlags(xmlNodePtr node, int flags) {
|
||||
switch (node->type) {
|
||||
case XML_DOCUMENT_NODE:
|
||||
case XML_HTML_DOCUMENT_NODE:
|
||||
((xmlDocPtr) node)->properties &= ~(flags << 27);
|
||||
return 0;
|
||||
|
||||
case XML_ATTRIBUTE_NODE:
|
||||
((xmlAttrPtr) node)->atype &= ~(flags << 27);
|
||||
return 0;
|
||||
|
||||
case XML_ELEMENT_NODE:
|
||||
case XML_TEXT_NODE:
|
||||
case XML_CDATA_SECTION_NODE:
|
||||
case XML_PI_NODE:
|
||||
case XML_COMMENT_NODE:
|
||||
node->extra &= ~(flags << 12);
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* xsltGetPSVIPtr:
|
||||
* @cur: Node
|
||||
*
|
||||
* Returns a pointer to the psvi member of a node or NULL on error.
|
||||
*/
|
||||
void **
|
||||
xsltGetPSVIPtr(xmlNodePtr cur) {
|
||||
switch (cur->type) {
|
||||
case XML_DOCUMENT_NODE:
|
||||
case XML_HTML_DOCUMENT_NODE:
|
||||
return &((xmlDocPtr) cur)->psvi;
|
||||
|
||||
case XML_ATTRIBUTE_NODE:
|
||||
return &((xmlAttrPtr) cur)->psvi;
|
||||
|
||||
case XML_ELEMENT_NODE:
|
||||
case XML_TEXT_NODE:
|
||||
case XML_CDATA_SECTION_NODE:
|
||||
case XML_PI_NODE:
|
||||
case XML_COMMENT_NODE:
|
||||
return &cur->psvi;
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WITH_PROFILER
|
||||
|
||||
/************************************************************************
|
||||
|
||||
@@ -244,6 +244,19 @@ XSLTPUBFUN xmlXPathCompExprPtr XSLTCALL
|
||||
const xmlChar *str,
|
||||
int flags);
|
||||
|
||||
#ifdef IN_LIBXSLT
|
||||
#define XSLT_SOURCE_NODE_MASK 15
|
||||
int
|
||||
xsltGetSourceNodeFlags(xmlNodePtr node);
|
||||
int
|
||||
xsltSetSourceNodeFlags(xsltTransformContextPtr ctxt, xmlNodePtr node,
|
||||
int flags);
|
||||
int
|
||||
xsltClearSourceNodeFlags(xmlNodePtr node, int flags);
|
||||
void **
|
||||
xsltGetPSVIPtr(xmlNodePtr cur);
|
||||
#endif
|
||||
|
||||
#ifdef WITH_PROFILER
|
||||
/*
|
||||
* Profiling.
|
||||
|
||||
Reference in New Issue
Block a user