diff options
-rw-r--r-- | src/compile.cc | 24 | ||||
-rw-r--r-- | src/compile.h | 20 | ||||
-rw-r--r-- | src/main.cc | 21 | ||||
-rw-r--r-- | src/node.cc | 7 | ||||
-rw-r--r-- | src/node.h | 29 | ||||
-rw-r--r-- | src/value.h | 4 | ||||
-rw-r--r-- | src/xpath.cc | 26 |
7 files changed, 115 insertions, 16 deletions
diff --git a/src/compile.cc b/src/compile.cc index fa17cf2a..b5d575a0 100644 --- a/src/compile.cc +++ b/src/compile.cc @@ -34,5 +34,29 @@ namespace ledger { namespace xml { +void entry_node_t::compile() +{ + typedef std::list<attributes_t::iterator> iterator_list; + + iterator_list to_update; + + for (attributes_t::iterator i = attributes->begin(); + i != attributes->end(); + i++) + if (i->first == DATE_ATTR && i->second.is_string()) + //i->second = parse_datetime(i->second.as_string().c_str()); + to_update.push_back(i); + + for (iterator_list::iterator i = to_update.begin(); + i != to_update.end(); + i++) { + attr_pair attr_def = **i; + attributes->erase(*i); + + attr_def.second = parse_datetime(attr_def.second.as_string().c_str()); + attributes->push_back(attr_def); + } +} + } // namespace xml } // namespace ledger diff --git a/src/compile.h b/src/compile.h index 3c0876e3..81319345 100644 --- a/src/compile.h +++ b/src/compile.h @@ -82,6 +82,26 @@ public: }; #endif +class entry_node_t : public parent_node_t +{ +public: + shared_ptr<entry_t> entry; + + entry_node_t(nameid_t _name_id, + document_t& _document, + const optional<parent_node_t&>& _parent = none, + entry_t * _entry = NULL) + : parent_node_t(_name_id, _document, _parent), entry(_entry) { + TRACE_CTOR(entry_node_t, "document_t&, parent_node_t, entry_t *"); + assert(_name_id == ENTRY_NODE); + } + virtual ~entry_node_t() { + TRACE_DTOR(entry_node_t); + } + + virtual void compile(); +}; + class transaction_node_t : public parent_node_t { public: diff --git a/src/main.cc b/src/main.cc index 2b9b71f0..a0bf035b 100644 --- a/src/main.cc +++ b/src/main.cc @@ -286,12 +286,27 @@ static int read_and_report(ledger::report_t& report, int argc, char * argv[], xpath.print(*out, doc_scope); *out << std::endl; + IF_INFO() { + *out << "Raw results:" << std::endl; + + foreach (const value_t& value, xpath.find_all(doc_scope)) { + if (value.is_xml_node()) + value.as_xml_node()->print(std::cout); + else + std::cout << value; + std::cout << std::endl; + } + + *out << "Compiled results:" << std::endl; + } + + xml_document.compile(); + foreach (const value_t& value, xpath.find_all(doc_scope)) { - if (value.is_xml_node()) { + if (value.is_xml_node()) value.as_xml_node()->print(std::cout); - } else { + else std::cout << value; - } std::cout << std::endl; } return 0; diff --git a/src/node.cc b/src/node.cc index 55b388e0..b03f5f5a 100644 --- a/src/node.cc +++ b/src/node.cc @@ -40,7 +40,7 @@ const char * node_t::name() const return *document().lookup_name(name_id()); } -optional<const string&> node_t::get_attr(const string& _name) const +optional<value_t> node_t::get_attr(const string& _name) const { optional<nameid_t> name_id = document().lookup_name_id(_name); if (name_id) @@ -71,12 +71,11 @@ void output_xml_string(std::ostream& out, const string& str) void node_t::print_attributes(std::ostream& out) const { - if (attributes) { - typedef attributes_t::nth_index<0>::type attributes_by_order; + if (attributes) foreach (const attr_pair& attr, attributes->get<0>()) out << ' ' << *document().lookup_name(attr.first) << "=\"" << attr.second << "\""; - } + IF_VERIFY() out << " type=\"parent_node_t\""; } @@ -50,13 +50,15 @@ class node_t : public supports_flags<>, public noncopyable public: typedef uint_fast16_t nameid_t; + // This has to be public so that multi_index_container can reference + // it in parent_node_t. nameid_t name_id_; protected: document_t& document_; optional<parent_node_t&> parent_; - typedef std::pair<nameid_t, string> attr_pair; + typedef std::pair<nameid_t, value_t> attr_pair; typedef multi_index_container< attr_pair, @@ -69,6 +71,11 @@ protected: optional<attributes_t> attributes; + typedef attributes_t::nth_index<0>::type attributes_by_order; + typedef attributes_t::nth_index<1>::type attributes_hashed; + + bool compiled; + public: node_t(nameid_t _name_id, document_t& _document, const optional<parent_node_t&>& _parent = none, flags_t _flags = 0) @@ -81,6 +88,11 @@ public: TRACE_DTOR(node_t); } + bool is_compiled() const { + return compiled; + } + virtual void compile() {} + bool is_parent_node() const { return has_flags(XML_NODE_IS_PARENT); } @@ -114,10 +126,16 @@ public: void set_attr(const nameid_t _name_id, const char * value) { if (! attributes) attributes = attributes_t(); + attributes->push_back(attr_pair(_name_id, string_value(value))); + } + void set_attr(const nameid_t _name_id, const value_t& value) { + if (! attributes) + attributes = attributes_t(); attributes->push_back(attr_pair(_name_id, value)); } - optional<const string&> get_attr(const string& _name) const; - optional<const string&> get_attr(const nameid_t _name_id) const { + + optional<value_t> get_attr(const string& _name) const; + optional<value_t> get_attr(const nameid_t _name_id) const { if (attributes) { typedef attributes_t::nth_index<1>::type attributes_by_name; @@ -159,6 +177,11 @@ public: clear_children(); } + virtual void compile() { + foreach (node_t * child, *this) + child->compile(); + } + template <typename T> T * create_child(nameid_t _name_id) { T * child = new T(_name_id, document(), *this); diff --git a/src/value.h b/src/value.h index 62bbca63..28024767 100644 --- a/src/value.h +++ b/src/value.h @@ -676,6 +676,10 @@ public: #define NULL_VALUE (value_t()) +inline value_t string_value(const string& str) { + return value_t(str, true); +} + std::ostream& operator<<(std::ostream& out, const value_t& val); DECLARE_EXCEPTION(value_error); diff --git a/src/xpath.cc b/src/xpath.cc index 46da665d..98988c64 100644 --- a/src/xpath.cc +++ b/src/xpath.cc @@ -433,23 +433,35 @@ namespace { value_t xpath_fn_last(xpath_t::call_scope_t& scope) { xpath_t::context_scope_t& context(CONTEXT_SCOPE(scope)); - return context.size(); } value_t xpath_fn_position(xpath_t::call_scope_t& scope) { xpath_t::context_scope_t& context(CONTEXT_SCOPE(scope)); - return context.index() + 1; } value_t xpath_fn_text(xpath_t::call_scope_t& scope) { xpath_t::context_scope_t& context(CONTEXT_SCOPE(scope)); - return value_t(context.xml_node().to_value().to_string(), true); } + + value_t xpath_fn_type(xpath_t::call_scope_t& scope) + { + if (scope.size() == 0) { + xpath_t::context_scope_t& context(CONTEXT_SCOPE(scope)); + return string_value(context.value().label()); + } + else if (scope.size() == 1) { + return string_value(scope[0].label()); + } + else { + assert(false); + return string_value("INVALID"); + } + } } xpath_t::ptr_op_t @@ -469,6 +481,8 @@ xpath_t::symbol_scope_t::lookup(const string& name) case 't': if (name == "text") return WRAP_FUNCTOR(bind(xpath_fn_text, _1)); + else if (name == "type") + return WRAP_FUNCTOR(bind(xpath_fn_type, _1)); break; } @@ -1194,10 +1208,10 @@ value_t xpath_t::op_t::calc(scope_t& scope) case ATTR_ID: case ATTR_NAME: - if (optional<const string&> value = - kind == ATTR_ID ? current_xml_node(scope).get_attr(as_long()) : + if (optional<value_t> value = + kind == ATTR_ID ? current_xml_node(scope).get_attr(as_name()) : current_xml_node(scope).get_attr(as_string())) - return value_t(*value, true); + return *value; else throw_(calc_error, "Attribute '" << (kind == ATTR_ID ? |