このページを編集する際は,編集に関する方針に従ってください.
概要
* at all xmlnodes that match a path * * The valid paths are a very small subset of xpath. * * The only predicates we support is for existence of attributes, or for attribute values, * we only support steps in the axis child and the axis must be ommited, * we support text() as a step. * * Examples: * - foo/bar/text() * - foo/bar[@baz='true']/text() * - foobar * - foobar[@attribute] * - *[@attribute='value']
- 妥当なpathはxpahtのサブセットだ。
引数
* @param parent the xmlnode where to start the path * @param path the path (xpath like syntax, but only a small subset) * @param xht hashtable mapping namespace prefixes to namespace IRIs * @return first item in the list of xmlnodes, or NULL if no xmlnode matched the path
実装
xmlnode_list_item xmlnode_get_tags(xmlnode context_node, const char *path, xht namespaces) { char *this_step = NULL; const char *ns_iri = NULL; char *next_step = NULL; char *start_predicate = NULL; char *end_predicate = NULL; char *predicate = NULL; char *end_prefix = NULL; int axis = 0; /* 0 = child, 1 = parent, 2 = attribute */ xmlnode_list_item result_first = NULL; xmlnode_list_item result_last = NULL; xmlnode iter = NULL;
/* sanity check */ if (context_node == NULL || path == NULL || namespaces == NULL) return NULL;
/* check if there is an axis */ if (j_strncmp(path, "child::", 7) == 0) { path = path+7; } else if (j_strncmp(path, "parent::", 8) == 0) { axis = 1; path = path+8; } else if (j_strncmp(path, "attribute::", 11) == 0) { axis = 2; path = path+11; }
/* separate this step from the next one, and check for a predicate in this step */ start_predicate = strchr(path, '['); next_step = strchr(path, '/');
- '['と'/'両方共無い
if (start_predicate == NULL && next_step == NULL) { this_step = pstrdup(xmlnode_pool(context_node), path);
- [が無いか、"/["の順である。
} else if (start_predicate == NULL || start_predicate > next_step && next_step != NULL) { this_step = pmalloco(xmlnode_pool(context_node), next_step - path + 1); snprintf(this_step, next_step - path + 1, "%s", path); if (next_step != NULL) next_step++;
} else { end_predicate = strchr(start_predicate, ']'); if (end_predicate == NULL) { /* error in predicate syntax */ return NULL; }
if (next_step != NULL) { if (next_step < end_predicate) next_step = strchr(end_predicate, '/'); if (next_step != NULL) next_step++; }
predicate = pmalloco(xmlnode_pool(context_node), end_predicate - start_predicate); snprintf(predicate, end_predicate - start_predicate, "%s", start_predicate+1); this_step = pmalloco(xmlnode_pool(context_node), start_predicate - path + 1); snprintf(this_step, start_predicate - path + 1, "%s", path); }
/* check for the namespace IRI we have to match the node */ end_prefix = strchr(this_step, ':'); if (end_prefix == NULL) { /* default prefix (or NULL if axis is attribute::) */ ns_iri = axis == 2 ? NULL : xhash_get(namespaces, ""); } else { /* prefixed name */ *end_prefix = 0; ns_iri = xhash_get(namespaces, this_step); this_step = end_prefix+1; }
/* iterate over all child nodes, checking if this step matches them */ for ( iter = axis == 0 ? xmlnode_get_firstchild(context_node) : axis == 1 ? xmlnode_get_parent(context_node) : axis == 2 ? xmlnode_get_firstattrib(context_node) : NULL; iter != NULL; iter = axis == 0 ? xmlnode_get_nextsibling(iter) : axis == 1 ? NULL : axis == 2 ? xmlnode_get_nextsibling(iter) : NULL) {
if (this_step != NULL && this_step[0] == '*' && this_step[1] == 0) { /* matching all nodes */
/* match ns_iri if prefix has been specified */ if (end_prefix != NULL) { if (iter->type == NTYPE_CDATA || j_strcmp(ns_iri, iter->ns_iri) != 0) { continue; } }
/* merging if it is a text node */ if (iter->type == NTYPE_CDATA) _xmlnode_merge(iter);
/* append to the result */ _xmlnode_append_if_predicate(&result_first, &result_last, iter, predicate, next_step, namespaces);
continue; }
if (iter->type == NTYPE_CDATA && j_strcmp(this_step, "text()") == 0) { /* matching text node */
/* merge all text nodes, that are direct siblings with this one */ _xmlnode_merge(iter);
/* append to the result */ _xmlnode_append_if_predicate(&result_first, &result_last, iter, predicate, next_step, namespaces);
continue; }
- 要素か属性を探す。
if ( iter->type != NTYPE_CDATA && (ns_iri == NULL && iter->ns_iri == NULL || j_strcmp(ns_iri, iter->ns_iri) == 0) && j_strcmp(this_step, iter->name) == 0 ) {
- ノードがCDATAでなく、ns_iriがともに等しく、ステップがノード名である場合。
/* matching element or attribute */
/* append to the result */ _xmlnode_append_if_predicate(&result_first, &result_last, iter, predicate, next_step, namespaces);
continue; } }
return result_first; }
呼出元
#related: relatedプラグインは廃止されました。