📄 c14n.c
字号:
}
if (!ctx->exclusive) {
ret = xmlC14NProcessNamespacesAxis(ctx, cur, visible);
} else {
ret = xmlExcC14NProcessNamespacesAxis(ctx, cur, visible);
}
if (ret < 0) {
xmlC14NErrInternal("processing namespaces axis");
return (-1);
}
/* todo: shouldn't this go to "visible only"? */
if(visible) {
xmlC14NVisibleNsStackShift(ctx->ns_rendered);
}
ret = xmlC14NProcessAttrsAxis(ctx, cur, visible);
if (ret < 0) {
xmlC14NErrInternal("processing attributes axis");
return (-1);
}
if (visible) {
xmlOutputBufferWriteString(ctx->buf, ">");
}
if (cur->children != NULL) {
ret = xmlC14NProcessNodeList(ctx, cur->children);
if (ret < 0) {
xmlC14NErrInternal("processing childrens list");
return (-1);
}
}
if (visible) {
xmlOutputBufferWriteString(ctx->buf, "</");
if ((cur->ns != NULL) && (xmlStrlen(cur->ns->prefix) > 0)) {
xmlOutputBufferWriteString(ctx->buf,
(const char *) cur->ns->prefix);
xmlOutputBufferWriteString(ctx->buf, ":");
}
xmlOutputBufferWriteString(ctx->buf, (const char *) cur->name);
xmlOutputBufferWriteString(ctx->buf, ">");
if (parent_is_doc) {
/* restore this flag from the stack for next node */
ctx->parent_is_doc = parent_is_doc;
ctx->pos = XMLC14N_AFTER_DOCUMENT_ELEMENT;
}
}
/*
* Restore ns_rendered stack position
*/
xmlC14NVisibleNsStackRestore(ctx->ns_rendered, &state);
return (0);
}
/**
* xmlC14NProcessNode:
* @ctx: the pointer to C14N context object
* @cur: the node to process
*
* Processes the given node
*
* Returns non-negative value on success or negative value on fail
*/
static int
xmlC14NProcessNode(xmlC14NCtxPtr ctx, xmlNodePtr cur)
{
int ret = 0;
int visible;
if ((ctx == NULL) || (cur == NULL)) {
xmlC14NErrParam("processing node");
return (-1);
}
visible = xmlC14NIsVisible(ctx, cur, cur->parent);
switch (cur->type) {
case XML_ELEMENT_NODE:
ret = xmlC14NProcessElementNode(ctx, cur, visible);
break;
case XML_CDATA_SECTION_NODE:
case XML_TEXT_NODE:
/*
* Text Nodes
* the string value, except all ampersands are replaced
* by &, all open angle brackets (<) are replaced by <, all closing
* angle brackets (>) are replaced by >, and all #xD characters are
* replaced by 
.
*/
/* cdata sections are processed as text nodes */
/* todo: verify that cdata sections are included in XPath nodes set */
if ((visible) && (cur->content != NULL)) {
xmlChar *buffer;
buffer = xmlC11NNormalizeText(cur->content);
if (buffer != NULL) {
xmlOutputBufferWriteString(ctx->buf,
(const char *) buffer);
xmlFree(buffer);
} else {
xmlC14NErrInternal("normalizing text node");
return (-1);
}
}
break;
case XML_PI_NODE:
/*
* Processing Instruction (PI) Nodes-
* The opening PI symbol (<?), the PI target name of the node,
* a leading space and the string value if it is not empty, and
* the closing PI symbol (?>). If the string value is empty,
* then the leading space is not added. Also, a trailing #xA is
* rendered after the closing PI symbol for PI children of the
* root node with a lesser document order than the document
* element, and a leading #xA is rendered before the opening PI
* symbol of PI children of the root node with a greater document
* order than the document element.
*/
if (visible) {
if (ctx->pos == XMLC14N_AFTER_DOCUMENT_ELEMENT) {
xmlOutputBufferWriteString(ctx->buf, "\x0A<?");
} else {
xmlOutputBufferWriteString(ctx->buf, "<?");
}
xmlOutputBufferWriteString(ctx->buf,
(const char *) cur->name);
if ((cur->content != NULL) && (*(cur->content) != '\0')) {
xmlChar *buffer;
xmlOutputBufferWriteString(ctx->buf, " ");
/* todo: do we need to normalize pi? */
buffer = xmlC11NNormalizePI(cur->content);
if (buffer != NULL) {
xmlOutputBufferWriteString(ctx->buf,
(const char *) buffer);
xmlFree(buffer);
} else {
xmlC14NErrInternal("normalizing pi node");
return (-1);
}
}
if (ctx->pos == XMLC14N_BEFORE_DOCUMENT_ELEMENT) {
xmlOutputBufferWriteString(ctx->buf, "?>\x0A");
} else {
xmlOutputBufferWriteString(ctx->buf, "?>");
}
}
break;
case XML_COMMENT_NODE:
/*
* Comment Nodes
* Nothing if generating canonical XML without comments. For
* canonical XML with comments, generate the opening comment
* symbol (<!--), the string value of the node, and the
* closing comment symbol (-->). Also, a trailing #xA is rendered
* after the closing comment symbol for comment children of the
* root node with a lesser document order than the document
* element, and a leading #xA is rendered before the opening
* comment symbol of comment children of the root node with a
* greater document order than the document element. (Comment
* children of the root node represent comments outside of the
* top-level document element and outside of the document type
* declaration).
*/
if (visible && ctx->with_comments) {
if (ctx->pos == XMLC14N_AFTER_DOCUMENT_ELEMENT) {
xmlOutputBufferWriteString(ctx->buf, "\x0A<!--");
} else {
xmlOutputBufferWriteString(ctx->buf, "<!--");
}
if (cur->content != NULL) {
xmlChar *buffer;
/* todo: do we need to normalize comment? */
buffer = xmlC11NNormalizeComment(cur->content);
if (buffer != NULL) {
xmlOutputBufferWriteString(ctx->buf,
(const char *) buffer);
xmlFree(buffer);
} else {
xmlC14NErrInternal("normalizing comment node");
return (-1);
}
}
if (ctx->pos == XMLC14N_BEFORE_DOCUMENT_ELEMENT) {
xmlOutputBufferWriteString(ctx->buf, "-->\x0A");
} else {
xmlOutputBufferWriteString(ctx->buf, "-->");
}
}
break;
case XML_DOCUMENT_NODE:
case XML_DOCUMENT_FRAG_NODE: /* should be processed as document? */
#ifdef LIBXML_DOCB_ENABLED
case XML_DOCB_DOCUMENT_NODE: /* should be processed as document? */
#endif
#ifdef LIBXML_HTML_ENABLED
case XML_HTML_DOCUMENT_NODE: /* should be processed as document? */
#endif
if (cur->children != NULL) {
ctx->pos = XMLC14N_BEFORE_DOCUMENT_ELEMENT;
ctx->parent_is_doc = 1;
ret = xmlC14NProcessNodeList(ctx, cur->children);
}
break;
case XML_ATTRIBUTE_NODE:
xmlC14NErrInvalidNode("XML_ATTRIBUTE_NODE", "processing node");
return (-1);
case XML_NAMESPACE_DECL:
xmlC14NErrInvalidNode("XML_NAMESPACE_DECL", "processing node");
return (-1);
case XML_ENTITY_REF_NODE:
xmlC14NErrInvalidNode("XML_ENTITY_REF_NODE", "processing node");
return (-1);
case XML_ENTITY_NODE:
xmlC14NErrInvalidNode("XML_ENTITY_NODE", "processing node");
return (-1);
case XML_DOCUMENT_TYPE_NODE:
case XML_NOTATION_NODE:
case XML_DTD_NODE:
case XML_ELEMENT_DECL:
case XML_ATTRIBUTE_DECL:
case XML_ENTITY_DECL:
#ifdef LIBXML_XINCLUDE_ENABLED
case XML_XINCLUDE_START:
case XML_XINCLUDE_END:
#endif
/*
* should be ignored according to "W3C Canonical XML"
*/
break;
default:
xmlC14NErrUnknownNode(cur->type, "processing node");
return (-1);
}
return (ret);
}
/**
* xmlC14NProcessNodeList:
* @ctx: the pointer to C14N context object
* @cur: the node to start from
*
* Processes all nodes in the row starting from cur.
*
* Returns non-negative value on success or negative value on fail
*/
static int
xmlC14NProcessNodeList(xmlC14NCtxPtr ctx, xmlNodePtr cur)
{
int ret;
if (ctx == NULL) {
xmlC14NErrParam("processing node list");
return (-1);
}
for (ret = 0; cur != NULL && ret >= 0; cur = cur->next) {
ret = xmlC14NProcessNode(ctx, cur);
}
return (ret);
}
/**
* xmlC14NFreeCtx:
* @ctx: the pointer to C14N context object
*
* Cleanups the C14N context object.
*/
static void
xmlC14NFreeCtx(xmlC14NCtxPtr ctx)
{
if (ctx == NULL) {
xmlC14NErrParam("freeing context");
return;
}
if (ctx->ns_rendered != NULL) {
xmlC14NVisibleNsStackDestroy(ctx->ns_rendered);
}
xmlFree(ctx);
}
/**
* xmlC14NNewCtx:
* @doc: the XML document for canonization
* @is_visible_callback:the function to use to determine is node visible
* or not
* @user_data: the first parameter for @is_visible_callback function
* (in most cases, it is nodes set)
* @inclusive_ns_prefixe the list of inclusive namespace prefixes
* ended with a NULL or NULL if there is no
* inclusive namespaces (only for exclusive
* canonicalization)
* @with_comments: include comments in the result (!=0) or not (==0)
* @buf: the output buffer to store canonical XML; this
* buffer MUST have encoder==NULL because C14N requires
* UTF-8 output
*
* Creates new C14N context object to store C14N parameters.
*
* Returns pointer to newly created object (success) or NULL (fail)
*/
static xmlC14NCtxPtr
xmlC14NNewCtx(xmlDocPtr doc,
xmlC14NIsVisibleCallback is_visible_callback, void* user_data,
int exclusive, xmlChar ** inclusive_ns_prefixes,
int with_comments, xmlOutputBufferPtr buf)
{
xmlC14NCtxPtr ctx = NULL;
if ((doc == NULL) || (buf == NULL)) {
xmlC14NErrParam("creating new context");
return (NULL);
}
/*
* Validate the encoding output buffer encoding
*/
if (buf->encoder != NULL) {
xmlC14NErr(ctx, (xmlNodePtr) doc, XML_C14N_REQUIRES_UTF8,
"xmlC14NNewCtx: output buffer encoder != NULL but C14N requires UTF8 output\n");
return (NULL);
}
/*
* Validate the XML document encoding value, if provided.
*/
if (doc->charset != XML_CHAR_ENCODING_UTF8) {
xmlC14NErr(ctx, (xmlNodePtr) doc, XML_C14N_REQUIRES_UTF8,
"xmlC14NNewCtx: source document not in UTF8\n");
return (NULL);
}
/*
* Allocate a new xmlC14NCtxPtr and fill the fields.
*/
ctx = (xmlC14NCtxPtr) xmlMalloc(sizeof(xmlC14NCtx));
if (ctx == NULL) {
xmlC14NErrMemory("creating context");
return (NULL);
}
memset(ctx, 0, sizeof(xmlC14NCtx));
/*
* initialize C14N context
*/
ctx->doc = doc;
ctx->with_comments = with_comments;
ctx->is_visible_callback = is_visible_callback;
ctx->user_data = user_data;
ctx->buf = buf;
ctx->parent_is_doc = 1;
ctx->pos = XMLC14N_BEFORE_DOCUMENT_ELEMENT;
ctx->ns_rendered = xmlC14NVisibleNsStackCreate();
if(ctx->ns_rendered == NULL) {
xmlC14NErr(ctx, (xmlNodePtr) doc, XML_C14N_CREATE_STACK,
"xmlC14NNewCtx: xmlC14NVisibleNsStackCreate failed\n");
xmlC14NFreeCtx(ctx);
return (NULL);
}
/*
* Set "exclusive" flag, create a nodes set for namespaces
* stack and remember list of incluseve prefixes
*/
if (exclusive) {
ctx->exclusive = 1;
ctx->inclusive_ns_prefixes = inclusive_ns_prefixes;
}
return (ctx);
}
/**
* xmlC14NExecute:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -