summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compile.cc24
-rw-r--r--src/compile.h20
-rw-r--r--src/main.cc21
-rw-r--r--src/node.cc7
-rw-r--r--src/node.h29
-rw-r--r--src/value.h4
-rw-r--r--src/xpath.cc26
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\"";
}
diff --git a/src/node.h b/src/node.h
index 7b1f9919..8d221049 100644
--- a/src/node.h
+++ b/src/node.h
@@ -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 ?