public
Description: ruby libxml library targetting speed and ease of use. provides an hpricot-like interface to xml
Homepage: http://trac.hasno.info/fastxml
Clone URL: git://github.com/segfault/fastxml.git
commit  9f39fd9cbbe80b654eafe1440811cb873d09afea
tree    5e5ed27203a3dfff55e4fdc5a31942a5babc6003
parent  93e12c6952c09403787ed9290cfe471f405e3360
fastxml / ext / fastxml_nodelist.c
100644 158 lines (126 sloc) 3.336 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/*
* $Id: fastxml_node.c 29 2007-08-16 05:16:47Z segfault $
*/
 
#include "fastxml.h"
#include "fastxml_node.h"
#include "fastxml_doc.h"
#include "fastxml_nodelist.h"
 
/* {{{ fastxml_nodelist
*/
VALUE fastxml_nodelist_inspect(VALUE self)
{
    VALUE dv;
    VALUE *argv;
    fxml_data_t *data;
 
    dv = rb_iv_get( self, "@lxml_doc" );
    Data_Get_Struct( dv, fxml_data_t, data );
 
    argv = ALLOCA_N( VALUE, 4 );
    argv[0] = rb_str_new2( "#<%s:0x%x %d>" );
    argv[1] = CLASS_OF( self );
    argv[2] = rb_obj_id( self );
    argv[3] = fastxml_nodelist_length( self );
    return rb_f_sprintf( 4, argv );
}
 
VALUE fastxml_nodelist_initialize(VALUE self)
{
    return self;
}
 
VALUE fastxml_nodelist_length(VALUE self)
{
    VALUE dv;
    xmlNodePtr cur;
    fxml_data_t *data;
 
    dv = rb_iv_get( self, "@lxml_doc" );
    Data_Get_Struct( dv, fxml_data_t, data );
  
  if (data->list_len == EMPTY_NODELIST) {
    data->list_len = 0;
    
        cur = data->list;
    while (cur != NULL) {
      data->list_len++;
      cur = cur->next;
    }
  }
  
  return rb_int2inum( data->list_len );
}
 
VALUE fastxml_nodelist_obj_to_ary(fxml_data_t *root)
{
  VALUE ret;
    xmlNodePtr cur = root->list;  
  
   ret = rb_ary_new();
    while (cur != NULL) {
        rb_ary_push( ret, fastxml_raw_node_to_obj( cur ) );
    cur = cur->next;
  }  
  
  return ret;
}
 
VALUE fastxml_nodeset_obj_to_ary(fxml_data_t *root)
{
  VALUE ret;
  xmlNodePtr cur, sub = NULL;
  int i;
 
   ret = rb_ary_new();
    if (root->xpath_obj->nodesetval->nodeTab != NULL) {
        cur = *root->xpath_obj->nodesetval->nodeTab;  
        for (i = 0; i < root->list_len; i++) {
            if (cur->type != XML_ELEMENT_NODE)
                continue;
            
            rb_ary_push( ret, fastxml_raw_node_to_obj( cur ) );
            sub = cur->next;
            while (sub != NULL) {
                rb_ary_push( ret, fastxml_raw_node_to_obj( sub ) );
                sub = sub->next;
            }
     cur++;
        }
    }
    
  
  return ret;
}
 
VALUE fastxml_nodelist_gen_list(VALUE self, fxml_data_t *data)
{
  VALUE lst = rb_iv_get( self, "@list" );
 
  if (lst == Qnil) {
        if (data->xpath_obj != NULL) {
      lst = fastxml_nodeset_obj_to_ary( data );
      rb_iv_set( self, "@list", lst );
    } else {
      lst = fastxml_nodelist_obj_to_ary( data );
      rb_iv_set( self, "@list", lst );
    }
  }
 
  return lst;
}
 
VALUE fastxml_nodelist_to_ary(VALUE self)
{
  VALUE dv;
  fxml_data_t *data;
  
  dv = rb_iv_get( self, "@lxml_doc" );
  Data_Get_Struct( dv, fxml_data_t, data );  
  return fastxml_nodelist_gen_list( self, data );    
}
 
VALUE fastxml_nodelist_each(VALUE self)
{
  VALUE lst, dv;
  fxml_data_t *data;
  int i;
  
  dv = rb_iv_get( self, "@lxml_doc" );
  Data_Get_Struct( dv, fxml_data_t, data );  
  lst = fastxml_nodelist_gen_list( self, data );
  
  for (i=0; i<RARRAY(lst)->len; i++) {
    rb_yield( RARRAY(lst)->ptr[i] );
    }
  
  return self;
}
 
VALUE fastxml_nodelist_entry(VALUE self, long idx)
{
  VALUE lst, dv;
  fxml_data_t *data;
  
  dv = rb_iv_get( self, "@lxml_doc" );
  Data_Get_Struct( dv, fxml_data_t, data );  
  lst = fastxml_nodelist_gen_list( self, data );
  if (idx > 0) // this comes in offset by 1
    idx = idx-1;
  // TODO: find out why this is provided offset by 1 and not 0-based
 
  return rb_ary_entry( lst, idx );
}
 
/* }}} fastxml_nodelist
*/