📄 apr_xml.c
字号:
default: msg = "There was an unknown error within the XML body."; break; } (void) apr_cpystrn(errbuf, msg, errbufsize); return errbuf;}APU_DECLARE(apr_status_t) apr_xml_parse_file(apr_pool_t *p, apr_xml_parser **parser, apr_xml_doc **ppdoc, apr_file_t *xmlfd, apr_size_t buffer_length){ apr_status_t rv; char *buffer; apr_size_t length; *parser = apr_xml_parser_create(p); if (*parser == NULL) { /* FIXME: returning an error code would be nice, * but we dont get one ;( */ return APR_EGENERAL; } buffer = apr_palloc(p, buffer_length); length = buffer_length; rv = apr_file_read(xmlfd, buffer, &length); while (rv == APR_SUCCESS) { rv = apr_xml_parser_feed(*parser, buffer, length); if (rv != APR_SUCCESS) { return rv; } length = buffer_length; rv = apr_file_read(xmlfd, buffer, &length); } if (rv != APR_EOF) { return rv; } rv = apr_xml_parser_done(*parser, ppdoc); *parser = NULL; return rv;}APU_DECLARE(void) apr_text_append(apr_pool_t * p, apr_text_header *hdr, const char *text){ apr_text *t = apr_palloc(p, sizeof(*t)); t->text = text; t->next = NULL; if (hdr->first == NULL) { /* no text elements yet */ hdr->first = hdr->last = t; } else { /* append to the last text element */ hdr->last->next = t; hdr->last = t; }}/* ---------------------------------------------------------------**** XML UTILITY FUNCTIONS*//*** apr_xml_quote_string: quote an XML string**** Replace '<', '>', and '&' with '<', '>', and '&'.** If quotes is true, then replace '"' with '"'.**** quotes is typically set to true for XML strings that will occur within** double quotes -- attribute values.*/APU_DECLARE(const char *) apr_xml_quote_string(apr_pool_t *p, const char *s, int quotes){ const char *scan; apr_size_t len = 0; apr_size_t extra = 0; char *qstr; char *qscan; char c; for (scan = s; (c = *scan) != '\0'; ++scan, ++len) { if (c == '<' || c == '>') extra += 3; /* < or > */ else if (c == '&') extra += 4; /* & */ else if (quotes && c == '"') extra += 5; /* " */ } /* nothing to do? */ if (extra == 0) return s; qstr = apr_palloc(p, len + extra + 1); for (scan = s, qscan = qstr; (c = *scan) != '\0'; ++scan) { if (c == '<') { *qscan++ = '&'; *qscan++ = 'l'; *qscan++ = 't'; *qscan++ = ';'; } else if (c == '>') { *qscan++ = '&'; *qscan++ = 'g'; *qscan++ = 't'; *qscan++ = ';'; } else if (c == '&') { *qscan++ = '&'; *qscan++ = 'a'; *qscan++ = 'm'; *qscan++ = 'p'; *qscan++ = ';'; } else if (quotes && c == '"') { *qscan++ = '&'; *qscan++ = 'q'; *qscan++ = 'u'; *qscan++ = 'o'; *qscan++ = 't'; *qscan++ = ';'; } else { *qscan++ = c; } } *qscan = '\0'; return qstr;}/* how many characters for the given integer? */#define APR_XML_NS_LEN(ns) ((ns) < 10 ? 1 : (ns) < 100 ? 2 : (ns) < 1000 ? 3 : \ (ns) < 10000 ? 4 : (ns) < 100000 ? 5 : \ (ns) < 1000000 ? 6 : (ns) < 10000000 ? 7 : \ (ns) < 100000000 ? 8 : (ns) < 1000000000 ? 9 : 10)static apr_size_t text_size(const apr_text *t){ apr_size_t size = 0; for (; t; t = t->next) size += strlen(t->text); return size;}static apr_size_t elem_size(const apr_xml_elem *elem, int style, apr_array_header_t *namespaces, int *ns_map){ apr_size_t size; if (style == APR_XML_X2T_FULL || style == APR_XML_X2T_FULL_NS_LANG) { const apr_xml_attr *attr; size = 0; if (style == APR_XML_X2T_FULL_NS_LANG) { int i; /* ** The outer element will contain xmlns:ns%d="%s" attributes ** and an xml:lang attribute, if applicable. */ for (i = namespaces->nelts; i--;) { /* compute size of: ' xmlns:ns%d="%s"' */ size += (9 + APR_XML_NS_LEN(i) + 2 + strlen(APR_XML_GET_URI_ITEM(namespaces, i)) + 1); } if (elem->lang != NULL) { /* compute size of: ' xml:lang="%s"' */ size += 11 + strlen(elem->lang) + 1; } } if (elem->ns == APR_XML_NS_NONE) { /* compute size of: <%s> */ size += 1 + strlen(elem->name) + 1; } else { int ns = ns_map ? ns_map[elem->ns] : elem->ns; /* compute size of: <ns%d:%s> */ size += 3 + APR_XML_NS_LEN(ns) + 1 + strlen(elem->name) + 1; } if (APR_XML_ELEM_IS_EMPTY(elem)) { /* insert a closing "/" */ size += 1; } else { /* * two of above plus "/": * <ns%d:%s> ... </ns%d:%s> * OR <%s> ... </%s> */ size = 2 * size + 1; } for (attr = elem->attr; attr; attr = attr->next) { if (attr->ns == APR_XML_NS_NONE) { /* compute size of: ' %s="%s"' */ size += 1 + strlen(attr->name) + 2 + strlen(attr->value) + 1; } else { /* compute size of: ' ns%d:%s="%s"' */ int ns = ns_map ? ns_map[attr->ns] : attr->ns; size += 3 + APR_XML_NS_LEN(ns) + 1 + strlen(attr->name) + 2 + strlen(attr->value) + 1; } } /* ** If the element has an xml:lang value that is *different* from ** its parent, then add the thing in: ' xml:lang="%s"'. ** ** NOTE: we take advantage of the pointer equality established by ** the parsing for "inheriting" the xml:lang values from parents. */ if (elem->lang != NULL && (elem->parent == NULL || elem->lang != elem->parent->lang)) { size += 11 + strlen(elem->lang) + 1; } } else if (style == APR_XML_X2T_LANG_INNER) { /* * This style prepends the xml:lang value plus a null terminator. * If a lang value is not present, then we insert a null term. */ size = elem->lang ? strlen(elem->lang) + 1 : 1; } else size = 0; size += text_size(elem->first_cdata.first); for (elem = elem->first_child; elem; elem = elem->next) { /* the size of the child element plus the CDATA that follows it */ size += (elem_size(elem, APR_XML_X2T_FULL, NULL, ns_map) + text_size(elem->following_cdata.first)); } return size;}static char *write_text(char *s, const apr_text *t){ for (; t; t = t->next) { apr_size_t len = strlen(t->text); memcpy(s, t->text, len); s += len; } return s;}static char *write_elem(char *s, const apr_xml_elem *elem, int style, apr_array_header_t *namespaces, int *ns_map){ const apr_xml_elem *child; apr_size_t len; int ns; if (style == APR_XML_X2T_FULL || style == APR_XML_X2T_FULL_NS_LANG) { int empty = APR_XML_ELEM_IS_EMPTY(elem); const apr_xml_attr *attr; if (elem->ns == APR_XML_NS_NONE) { len = sprintf(s, "<%s", elem->name); } else { ns = ns_map ? ns_map[elem->ns] : elem->ns; len = sprintf(s, "<ns%d:%s", ns, elem->name); } s += len; for (attr = elem->attr; attr; attr = attr->next) { if (attr->ns == APR_XML_NS_NONE) len = sprintf(s, " %s=\"%s\"", attr->name, attr->value); else { ns = ns_map ? ns_map[attr->ns] : attr->ns; len = sprintf(s, " ns%d:%s=\"%s\"", ns, attr->name, attr->value); } s += len; } /* add the xml:lang value if necessary */ if (elem->lang != NULL && (style == APR_XML_X2T_FULL_NS_LANG || elem->parent == NULL || elem->lang != elem->parent->lang)) { len = sprintf(s, " xml:lang=\"%s\"", elem->lang); s += len; } /* add namespace definitions, if required */ if (style == APR_XML_X2T_FULL_NS_LANG) { int i; for (i = namespaces->nelts; i--;) { len = sprintf(s, " xmlns:ns%d=\"%s\"", i, APR_XML_GET_URI_ITEM(namespaces, i)); s += len; } } /* no more to do. close it up and go. */ if (empty) { *s++ = '/'; *s++ = '>'; return s; } /* just close it */ *s++ = '>'; } else if (style == APR_XML_X2T_LANG_INNER) { /* prepend the xml:lang value */ if (elem->lang != NULL) { len = strlen(elem->lang); memcpy(s, elem->lang, len); s += len; } *s++ = '\0'; } s = write_text(s, elem->first_cdata.first); for (child = elem->first_child; child; child = child->next) { s = write_elem(s, child, APR_XML_X2T_FULL, NULL, ns_map); s = write_text(s, child->following_cdata.first); } if (style == APR_XML_X2T_FULL || style == APR_XML_X2T_FULL_NS_LANG) { if (elem->ns == APR_XML_NS_NONE) { len = sprintf(s, "</%s>", elem->name); } else { ns = ns_map ? ns_map[elem->ns] : elem->ns; len = sprintf(s, "</ns%d:%s>", ns, elem->name); } s += len; } return s;}APU_DECLARE(void) apr_xml_quote_elem(apr_pool_t *p, apr_xml_elem *elem){ apr_text *scan_txt; apr_xml_attr *scan_attr; apr_xml_elem *scan_elem; /* convert the element's text */ for (scan_txt = elem->first_cdata.first; scan_txt != NULL; scan_txt = scan_txt->next) { scan_txt->text = apr_xml_quote_string(p, scan_txt->text, 0); } for (scan_txt = elem->following_cdata.first; scan_txt != NULL; scan_txt = scan_txt->next) { scan_txt->text = apr_xml_quote_string(p, scan_txt->text, 0); } /* convert the attribute values */ for (scan_attr = elem->attr; scan_attr != NULL; scan_attr = scan_attr->next) { scan_attr->value = apr_xml_quote_string(p, scan_attr->value, 1); } /* convert the child elements */ for (scan_elem = elem->first_child; scan_elem != NULL; scan_elem = scan_elem->next) { apr_xml_quote_elem(p, scan_elem); }}/* convert an element to a text string */APU_DECLARE(void) apr_xml_to_text(apr_pool_t * p, const apr_xml_elem *elem, int style, apr_array_header_t *namespaces, int *ns_map, const char **pbuf, apr_size_t *psize){ /* get the exact size, plus a null terminator */ apr_size_t size = elem_size(elem, style, namespaces, ns_map) + 1; char *s = apr_palloc(p, size); (void) write_elem(s, elem, style, namespaces, ns_map); s[size - 1] = '\0'; *pbuf = s; if (psize) *psize = size;}APU_DECLARE(const char *) apr_xml_empty_elem(apr_pool_t * p, const apr_xml_elem *elem){ if (elem->ns == APR_XML_NS_NONE) { /* * The prefix (xml...) is already within the prop name, or * the element simply has no prefix. */ return apr_psprintf(p, "<%s/>" DEBUG_CR, elem->name); } return apr_psprintf(p, "<ns%d:%s/>" DEBUG_CR, elem->ns, elem->name);}/* return the URI's (existing) index, or insert it and return a new index */APU_DECLARE(int) apr_xml_insert_uri(apr_array_header_t *uri_array, const char *uri){ int i; const char **pelt; /* never insert an empty URI; this index is always APR_XML_NS_NONE */ if (*uri == '\0') return APR_XML_NS_NONE; for (i = uri_array->nelts; i--;) { if (strcmp(uri, APR_XML_GET_URI_ITEM(uri_array, i)) == 0) return i; } pelt = apr_array_push(uri_array); *pelt = uri; /* assume uri is const or in a pool */ return uri_array->nelts - 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -