| 1 | /* |
|---|
| 2 | * Document-class: FastXml::AttrList |
|---|
| 3 | * |
|---|
| 4 | * call-seq: |
|---|
| 5 | * doc = FastXml( docfile ) # from FastXml::Doc |
|---|
| 6 | * n = doc.root # pull the root node |
|---|
| 7 | * attrlist = n.attr # pull the FastXml::AttrList for the node |
|---|
| 8 | * puts attrlist[:some_attr] |
|---|
| 9 | * puts attrlist["some_attr"] |
|---|
| 10 | */ |
|---|
| 11 | // Please see the LICENSE file for copyright, licensing and distribution information |
|---|
| 12 | |
|---|
| 13 | #include "fastxml.h" |
|---|
| 14 | #include "fastxml_node.h" |
|---|
| 15 | #include "fastxml_doc.h" |
|---|
| 16 | #include "fastxml_nodelist.h" |
|---|
| 17 | #include "fastxml_attrlist.h" |
|---|
| 18 | |
|---|
| 19 | /* {{{ fastml_attr_list |
|---|
| 20 | */ |
|---|
| 21 | void Init_fastxml_attrlist() |
|---|
| 22 | { |
|---|
| 23 | #ifdef RDOC_SHOULD_BE_SMARTER__THIS_IS_NEVER_RUN |
|---|
| 24 | rb_mFastXml = rb_define_module( "FastXml" ); |
|---|
| 25 | #endif |
|---|
| 26 | rb_cFastXmlAttrList = rb_define_class_under( rb_mFastXml, "AttrList", rb_cObject ); |
|---|
| 27 | |
|---|
| 28 | rb_include_module( rb_cFastXmlAttrList, rb_mEnumerable ); |
|---|
| 29 | rb_define_method( rb_cFastXmlAttrList, "initialize", fastxml_attrlist_initialize, 0 ); |
|---|
| 30 | rb_define_method( rb_cFastXmlAttrList, "[]", fastxml_attrlist_indexer, 1 ); |
|---|
| 31 | rb_define_method( rb_cFastXmlAttrList, "[]=", fastxml_attrlist_indexer_set, 2 ); |
|---|
| 32 | rb_define_method( rb_cFastXmlAttrList, "include?", fastxml_attrlist_include, 1 ); |
|---|
| 33 | } |
|---|
| 34 | |
|---|
| 35 | VALUE fastxml_attrlist_initialize(VALUE self) |
|---|
| 36 | { |
|---|
| 37 | return self; |
|---|
| 38 | } |
|---|
| 39 | |
|---|
| 40 | /* Returns the value of the attribute with the provided attr_name |
|---|
| 41 | * as a string. |
|---|
| 42 | * nil if the attribute does not exist. |
|---|
| 43 | * |
|---|
| 44 | * call-seq: |
|---|
| 45 | * puts node.attr[:an_attr_name] |
|---|
| 46 | */ |
|---|
| 47 | VALUE fastxml_attrlist_indexer(VALUE self, VALUE attr_name) |
|---|
| 48 | { |
|---|
| 49 | VALUE ret, dv, attr_raw_str; |
|---|
| 50 | fxml_data_t *data; |
|---|
| 51 | xmlChar *raw_ret, *name_str; |
|---|
| 52 | |
|---|
| 53 | if (attr_name == Qnil) |
|---|
| 54 | return Qnil; |
|---|
| 55 | |
|---|
| 56 | dv = rb_iv_get( self, "@lxml_doc" ); |
|---|
| 57 | Data_Get_Struct( dv, fxml_data_t, data ); |
|---|
| 58 | |
|---|
| 59 | attr_raw_str = rb_funcall( attr_name, s_to_s, 0 ); |
|---|
| 60 | name_str = (xmlChar*)StringValuePtr( attr_raw_str ); |
|---|
| 61 | raw_ret = xmlGetProp( data->node, name_str ); |
|---|
| 62 | if (raw_ret == NULL) |
|---|
| 63 | return Qnil; |
|---|
| 64 | |
|---|
| 65 | ret = rb_str_new2( (const char*)raw_ret ); |
|---|
| 66 | xmlFree( raw_ret ); |
|---|
| 67 | |
|---|
| 68 | return ret; |
|---|
| 69 | } |
|---|
| 70 | |
|---|
| 71 | /* Assignes a value to the attribute with the provided attr_name. |
|---|
| 72 | * if the value provided is nil, the attribute is removed from the element. |
|---|
| 73 | * |
|---|
| 74 | * call-seq: |
|---|
| 75 | * node.attr[:an_attr_name] = "testing" # adds the attribute if it doesn't exist |
|---|
| 76 | * node.attr[:an_attr_name] = nil # removes the attribute if it exists |
|---|
| 77 | */ |
|---|
| 78 | VALUE fastxml_attrlist_indexer_set(VALUE self, VALUE attr_name, VALUE attr_value) |
|---|
| 79 | { |
|---|
| 80 | VALUE dv, attr_raw_str; |
|---|
| 81 | fxml_data_t *data; |
|---|
| 82 | xmlChar *val, *name_str; |
|---|
| 83 | |
|---|
| 84 | if (attr_name == Qnil) |
|---|
| 85 | return Qnil; |
|---|
| 86 | |
|---|
| 87 | dv = rb_iv_get( self, "@lxml_doc" ); |
|---|
| 88 | Data_Get_Struct( dv, fxml_data_t, data ); |
|---|
| 89 | |
|---|
| 90 | attr_raw_str = rb_funcall( attr_name, s_to_s, 0 ); |
|---|
| 91 | name_str = (xmlChar*)StringValuePtr( attr_raw_str ); |
|---|
| 92 | |
|---|
| 93 | if (attr_value == Qnil) { |
|---|
| 94 | xmlUnsetProp( data->node, name_str ); // don't care if the node doesn't exist, as the end result is the same. |
|---|
| 95 | } else { |
|---|
| 96 | val = (xmlChar*)StringValuePtr( attr_value ); |
|---|
| 97 | |
|---|
| 98 | xmlSetProp( data->node, name_str, val ); |
|---|
| 99 | } |
|---|
| 100 | |
|---|
| 101 | |
|---|
| 102 | return attr_value; |
|---|
| 103 | } |
|---|
| 104 | |
|---|
| 105 | /* Returns True if the FastXml::AttrList contains an attribute |
|---|
| 106 | * with the specified attr_name. Returns nil otherwise. |
|---|
| 107 | * |
|---|
| 108 | * call-seq: |
|---|
| 109 | * puts "FAIL" unless node.attr.include?(:a_required_node) |
|---|
| 110 | */ |
|---|
| 111 | VALUE fastxml_attrlist_include(VALUE self, VALUE attr_name) |
|---|
| 112 | { |
|---|
| 113 | VALUE dv, attr_raw_str; |
|---|
| 114 | fxml_data_t *data; |
|---|
| 115 | xmlChar *raw_ret, *name_str; |
|---|
| 116 | |
|---|
| 117 | if (attr_name == Qnil) |
|---|
| 118 | return Qnil; |
|---|
| 119 | |
|---|
| 120 | dv = rb_iv_get( self, "@lxml_doc" ); |
|---|
| 121 | Data_Get_Struct( dv, fxml_data_t, data ); |
|---|
| 122 | |
|---|
| 123 | attr_raw_str = rb_funcall( attr_name, s_to_s, 0 ); |
|---|
| 124 | name_str = (xmlChar*)StringValuePtr( attr_raw_str ); |
|---|
| 125 | raw_ret = xmlGetProp( data->node, name_str ); |
|---|
| 126 | if (raw_ret == NULL) |
|---|
| 127 | return Qnil; |
|---|
| 128 | |
|---|
| 129 | return Qtrue; |
|---|
| 130 | } |
|---|
| 131 | |
|---|
| 132 | |
|---|
| 133 | /* }}} fastxml_attr_list |
|---|
| 134 | */ |
|---|