Logo Search packages:      
Sourcecode: jabberd14 version File versions  Download package

xmlnode_list_item xmlnode_get_tags ( xmlnode  context_node,
const char *  path,
xht  namespaces,
pool  p 
)

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']

Parameters:
context_node the xmlnode where to start the path
path the path (xpath like syntax, but only a small subset)
namespaces hashtable mapping namespace prefixes to namespace IRIs
p memory pool to use
Returns:
first item in the list of xmlnodes, or NULL if no xmlnode matched the path

Definition at line 879 of file xmlnode.cc.

References _xmlnode_append_if_predicate(), _xmlnode_merge(), j_strcmp(), j_strncmp(), pmalloco(), pstrdup(), xhash_get(), xmlnode_get_firstattrib(), xmlnode_get_firstchild(), xmlnode_get_nextsibling(), xmlnode_get_parent(), and xmlnode_pool().

Referenced by _jabberd_atexit(), _js_authreg_register(), _js_session_from(), _js_session_to(), _jsm_deserialize_session(), _jsm_deserialize_xml(), _mio_access_check(), _mio_connect(), _mod_register_server_register(), _xdb_sql_create_preprocessed_sql_list(), _xmlnode_append_if_predicate(), acl_get_users(), base_dir_config(), configurate(), dialback(), dialback_in_verify(), dialback_out_read(), dialback_packets(), js_config(), jsm(), jsm_deserialize(), jutil_priority(), mio_init(), mod_admin_message(), mod_agents_agent(), mod_announce_sess_avail(), mod_auth_crypt_jane(), mod_auth_crypt_pwchange(), mod_auth_crypt_reg(), mod_auth_crypt_reset(), mod_auth_digest_pwchange(), mod_auth_digest_reg(), mod_auth_digest_yum(), mod_auth_plain_jane(), mod_auth_plain_pwchange(), mod_auth_plain_reg(), mod_browse_get(), mod_browse_reply(), mod_disco_user_info(), mod_disco_user_items(), mod_example_server(), mod_last_sess_end(), mod_offline(), mod_offline_check_expired(), mod_offline_deserialize(), mod_offline_message(), mod_offline_out_available(), mod_presence_deserialize(), mod_presence_out(), mod_privacy_activate_list(), mod_privacy_activate_named(), mod_privacy_compile_list(), mod_privacy_deserialize(), mod_privacy_insert_rostergroup(), mod_privacy_load_offline_list(), mod_privacy_out_iq_get(), mod_privacy_out_iq_set(), mod_privacy_out_iq_set_default(), mod_privacy_out_iq_set_list(), mod_register_check(), mod_register_new(), mod_register_passwordchange(), mod_roster_delete(), mod_roster_out_iq(), mod_roster_s10n(), mod_useridpolicy_new(), mod_vcard_jud(), mod_vcard_set(), mod_version(), mod_xml(), mod_xml_set(), register_instance(), xdb_file(), xdb_file_phandler(), xdb_sql(), xdb_sql_construct_query(), xdb_sql_handler_process(), xdb_sql_mysql_init(), xdb_sql_postgresql_init(), and xhash_from_xml().

                                                                                                   {
    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;

    /* if no memory pool specified use the memory pool of the context_node */
    if (p == NULL) {
      p = xmlnode_pool(context_node);
    }

    /* 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(p, path);
    } else if (start_predicate == NULL || start_predicate > next_step && next_step != NULL) {
      this_step = static_cast<char*>(pmalloco(p, 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 = static_cast<char*>(pmalloco(p, end_predicate - start_predicate));
      snprintf(predicate, end_predicate - start_predicate, "%s", start_predicate+1);
      this_step = static_cast<char*>(pmalloco(p, 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 : static_cast<const char*>(xhash_get(namespaces, ""));
    } else {
      /* prefixed name */
      *end_prefix = 0;
      ns_iri = static_cast<const char*>(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, p);

          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, p);

          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) {
          /* matching element or attribute */

          /* append to the result */
          _xmlnode_append_if_predicate(&result_first, &result_last, iter, predicate, next_step, namespaces, p);

          continue;
      }
    }

    return result_first;
}


Generated by  Doxygen 1.6.0   Back to index