summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2009-11-09 03:42:06 -0500
committerJohn Wiegley <johnw@newartisans.com>2009-11-09 03:42:35 -0500
commit6cdb79e2a611d99fa6e13dd224a92dc8badaf2ac (patch)
tree967464fc8bda9543a108d83d3fc96ecdffb4e04c /src
parent2c80227339538154ad0869e746f52db805325589 (diff)
downloadfork-ledger-6cdb79e2a611d99fa6e13dd224a92dc8badaf2ac.tar.gz
fork-ledger-6cdb79e2a611d99fa6e13dd224a92dc8badaf2ac.tar.bz2
fork-ledger-6cdb79e2a611d99fa6e13dd224a92dc8badaf2ac.zip
XML reporting now works via the "xml" command
Diffstat (limited to 'src')
-rw-r--r--src/amount.cc8
-rw-r--r--src/amount.h3
-rw-r--r--src/annotate.h8
-rw-r--r--src/commodity.cc44
-rw-r--r--src/commodity.h8
-rw-r--r--src/post.cc95
-rw-r--r--src/post.h2
-rw-r--r--src/report.cc2
-rw-r--r--src/times.h22
-rw-r--r--src/utils.h21
-rw-r--r--src/value.cc17
-rw-r--r--src/xact.cc59
-rw-r--r--src/xact.h2
-rw-r--r--src/xml.cc42
14 files changed, 265 insertions, 68 deletions
diff --git a/src/amount.cc b/src/amount.cc
index 456ef8cf..6fb0056b 100644
--- a/src/amount.cc
+++ b/src/amount.cc
@@ -1125,16 +1125,16 @@ bool amount_t::valid() const
return true;
}
-void to_xml(std::ostream& out, const amount_t& amt)
+void to_xml(std::ostream& out, const amount_t& amt, bool commodity_details)
{
push_xml x(out, "amount");
if (amt.has_commodity())
- to_xml(out, amt.commodity());
+ to_xml(out, amt.commodity(), commodity_details);
{
- push_xml y(out, "number");
- out << amt.number();
+ push_xml y(out, "quantity");
+ out << y.guard(amt.quantity_string());
}
}
diff --git a/src/amount.h b/src/amount.h
index d8a19f91..505e2ea7 100644
--- a/src/amount.h
+++ b/src/amount.h
@@ -745,7 +745,8 @@ inline std::istream& operator>>(std::istream& in, amount_t& amt) {
return in;
}
-void to_xml(std::ostream& out, const amount_t& amt);
+void to_xml(std::ostream& out, const amount_t& amt,
+ bool commodity_details = false);
} // namespace ledger
diff --git a/src/annotate.h b/src/annotate.h
index 37810fb9..38ebaeae 100644
--- a/src/annotate.h
+++ b/src/annotate.h
@@ -116,19 +116,19 @@ inline void to_xml(std::ostream& out, const annotation_t& details)
if (details.price)
{
- push_xml y(out, "ann-price");
+ push_xml y(out, "price");
to_xml(out, *details.price);
}
if (details.date)
{
- push_xml y(out, "ann-date");
- to_xml(out, *details.date);
+ push_xml y(out, "date");
+ to_xml(out, *details.date, false);
}
if (details.tag)
{
- push_xml y(out, "ann-tag");
+ push_xml y(out, "tag");
out << y.guard(*details.tag);
}
}
diff --git a/src/commodity.cc b/src/commodity.cc
index 7669b3db..49e82b53 100644
--- a/src/commodity.cc
+++ b/src/commodity.cc
@@ -654,15 +654,51 @@ bool compare_amount_commodities::operator()(const amount_t * left,
}
}
-void to_xml(std::ostream& out, const commodity_t& comm)
+void to_xml(std::ostream& out, const commodity_t& comm,
+ bool commodity_details)
{
- push_xml x(out, "commodity");
+ push_xml x(out, "commodity", true);
+
+ out << " flags=\"";
+ if (! (comm.has_flags(COMMODITY_STYLE_SUFFIXED))) out << 'P';
+ if (comm.has_flags(COMMODITY_STYLE_SEPARATED)) out << 'S';
+ if (comm.has_flags(COMMODITY_STYLE_THOUSANDS)) out << 'T';
+ if (comm.has_flags(COMMODITY_STYLE_EUROPEAN)) out << 'E';
+ out << '"';
+
+ x.close_attrs();
+
{
push_xml y(out, "symbol");
out << y.guard(comm.symbol());
}
- if (comm.is_annotated())
- to_xml(out, as_annotated_commodity(comm).details);
+
+ if (commodity_details) {
+ if (comm.is_annotated())
+ to_xml(out, as_annotated_commodity(comm).details);
+
+ if (comm.varied_history()) {
+ push_xml y(out, "varied-history");
+
+ foreach (const commodity_t::history_by_commodity_map::value_type& pair,
+ comm.varied_history()->histories) {
+ {
+ push_xml z(out, "symbol");
+ out << y.guard(pair.first->symbol());
+ }
+ {
+ push_xml z(out, "history");
+
+ foreach (const commodity_t::history_map::value_type& inner_pair,
+ pair.second.prices) {
+ push_xml w(out, "price-point");
+ to_xml(out, inner_pair.first);
+ to_xml(out, inner_pair.second);
+ }
+ }
+ }
+ }
+ }
}
} // namespace ledger
diff --git a/src/commodity.h b/src/commodity.h
index ef9ef5c4..42cc6d8f 100644
--- a/src/commodity.h
+++ b/src/commodity.h
@@ -318,6 +318,11 @@ public:
return *base->varied_history;
return none;
}
+ optional<const varied_history_t&> varied_history() const {
+ if (base->varied_history)
+ return *base->varied_history;
+ return none;
+ }
optional<history_t&> history(const optional<commodity_t&>& commodity);
@@ -418,7 +423,8 @@ struct compare_amount_commodities {
bool operator()(const amount_t * left, const amount_t * right) const;
};
-void to_xml(std::ostream& out, const commodity_t& comm);
+void to_xml(std::ostream& out, const commodity_t& comm,
+ bool commodity_details = false);
} // namespace ledger
diff --git a/src/post.cc b/src/post.cc
index 0fd763a9..24705323 100644
--- a/src/post.cc
+++ b/src/post.cc
@@ -452,4 +452,99 @@ void post_t::set_reported_account(account_t * account)
account->xdata().reported_posts.push_back(this);
}
+void to_xml(std::ostream& out, const post_t& post)
+{
+ push_xml x(out, "posting", true);
+
+ if (post.state() == item_t::CLEARED)
+ out << " state=\"cleared\"";
+ else if (post.state() == item_t::PENDING)
+ out << " state=\"pending\"";
+
+ if (post.has_flags(POST_VIRTUAL))
+ out << " virtual=\"true\"";
+ if (post.has_flags(ITEM_GENERATED))
+ out << " generated=\"true\"";
+
+ x.close_attrs();
+
+ if (post._date) {
+ push_xml y(out, "date");
+ to_xml(out, *post._date, false);
+ }
+ if (post._date_eff) {
+ push_xml y(out, "effective-date");
+ to_xml(out, *post._date_eff, false);
+ }
+
+ if (post.account) {
+ push_xml y(out, "account", true);
+
+ out << " ref=\"";
+ out.width(sizeof(unsigned long) * 2);
+ out.fill('0');
+ out << std::hex << reinterpret_cast<unsigned long>(post.account);
+ out << '"';
+ y.close_attrs();
+
+ {
+ push_xml z(out, "name");
+ out << z.guard(post.account->fullname());
+ }
+ }
+
+ {
+ push_xml y(out, "post-amount");
+ if (post.has_xdata() && post.xdata().has_flags(POST_EXT_COMPOUND))
+ to_xml(out, post.xdata().compound_value);
+ else
+ to_xml(out, post.amount);
+ }
+
+ if (post.cost) {
+ push_xml y(out, "cost");
+ to_xml(out, *post.cost);
+ }
+
+ if (post.assigned_amount) {
+ if (post.has_flags(POST_CALCULATED)) {
+ push_xml y(out, "balance-assertion");
+ to_xml(out, *post.assigned_amount);
+ } else {
+ push_xml y(out, "balance-assignment");
+ to_xml(out, *post.assigned_amount);
+ }
+ }
+
+ if (post.note) {
+ push_xml y(out, "note");
+ out << y.guard(*post.note);
+ }
+
+ if (post.metadata) {
+ push_xml y(out, "metadata");
+ foreach (const item_t::string_map::value_type& pair, *post.metadata) {
+ if (pair.second) {
+ push_xml z(out, "variable");
+ {
+ push_xml z(out, "key");
+ out << y.guard(pair.first);
+ }
+ {
+ push_xml z(out, "value");
+ out << y.guard(*pair.second);
+ }
+ } else {
+ push_xml z(out, "tag");
+ out << y.guard(pair.first);
+ }
+ }
+ }
+
+ if (post.xdata_ && ! post.xdata_->total.is_null()) {
+ push_xml y(out, "total");
+ to_xml(out, post.xdata_->total);
+ }
+}
+
} // namespace ledger
diff --git a/src/post.h b/src/post.h
index 8f51ca84..addf0629 100644
--- a/src/post.h
+++ b/src/post.h
@@ -218,6 +218,8 @@ private:
#endif // HAVE_BOOST_SERIALIZATION
};
+void to_xml(std::ostream& out, const post_t& post);
+
} // namespace ledger
#endif // _POST_H
diff --git a/src/report.cc b/src/report.cc
index 1443dd91..24f0c054 100644
--- a/src/report.cc
+++ b/src/report.cc
@@ -982,6 +982,8 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind,
case 'x':
if (is_eq(p, "xact"))
return WRAP_FUNCTOR(xact_command);
+ else if (is_eq(p, "xml"))
+ return WRAP_FUNCTOR(reporter<>(new format_xml(*this), *this, "#xml"));
break;
}
break;
diff --git a/src/times.h b/src/times.h
index c2c2530e..3cd359d2 100644
--- a/src/times.h
+++ b/src/times.h
@@ -116,16 +116,26 @@ std::string format_date(const date_t& when,
void set_date_format(const char * format);
void set_input_date_format(const char * format);
-inline void to_xml(std::ostream& out, const datetime_t& when)
+inline void to_xml(std::ostream& out, const datetime_t& when,
+ bool wrap = true)
{
- push_xml x(out, "datetime");
- out << format_datetime(when, FMT_WRITTEN);
+ if (wrap) {
+ push_xml x(out, "datetime");
+ out << format_datetime(when, FMT_WRITTEN);
+ } else {
+ out << format_datetime(when, FMT_WRITTEN);
+ }
}
-inline void to_xml(std::ostream& out, const date_t& when)
+inline void to_xml(std::ostream& out, const date_t& when,
+ bool wrap = true)
{
- push_xml x(out, "date");
- out << format_date(when, FMT_WRITTEN);
+ if (wrap) {
+ push_xml x(out, "date");
+ out << format_date(when, FMT_WRITTEN);
+ } else {
+ out << format_date(when, FMT_WRITTEN);
+ }
}
class date_interval_t : public equality_comparable<date_interval_t>
diff --git a/src/utils.h b/src/utils.h
index 6bd67146..bfdee0b2 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -649,16 +649,27 @@ inline string to_hex(uint_least32_t * message_digest, const int len = 1)
class push_xml
{
std::ostream& out;
- string tag;
+ string tag;
+ bool leave_open;
+
public:
- push_xml(std::ostream& _out, const string& _tag) : out(_out), tag(_tag) {
- out << '<' << tag << '>';
+ push_xml(std::ostream& _out, const string& _tag, bool has_attrs = false,
+ bool _leave_open = false)
+ : out(_out), tag(_tag), leave_open(_leave_open) {
+ out << '<' << tag;
+ if (! has_attrs)
+ out << '>';
}
~push_xml() {
- out << "</" << tag << '>';
+ if (! leave_open)
+ out << "</" << tag << '>';
+ }
+
+ void close_attrs() {
+ out << '>';
}
- string guard(const string& str) {
+ static string guard(const string& str) {
std::ostringstream buf;
foreach (const char& ch, str) {
switch (ch) {
diff --git a/src/value.cc b/src/value.cc
index 2029b9c5..b4060a1c 100644
--- a/src/value.cc
+++ b/src/value.cc
@@ -1748,8 +1748,6 @@ bool sort_value_is_less_than(const std::list<sort_value_t>& left_values,
void to_xml(std::ostream& out, const value_t& value)
{
- push_xml x(out, "value");
-
switch (value.type()) {
case value_t::VOID:
out << "<void />";
@@ -1764,6 +1762,14 @@ void to_xml(std::ostream& out, const value_t& value)
out << value.as_long();
break;
}
+
+ case value_t::AMOUNT:
+ to_xml(out, value.as_amount());
+ break;
+ case value_t::BALANCE:
+ to_xml(out, value.as_balance());
+ break;
+
case value_t::DATETIME:
to_xml(out, value.as_datetime());
break;
@@ -1786,13 +1792,6 @@ void to_xml(std::ostream& out, const value_t& value)
break;
}
- case value_t::AMOUNT:
- to_xml(out, value.as_amount());
- break;
- case value_t::BALANCE:
- to_xml(out, value.as_balance());
- break;
-
case value_t::SCOPE:
default:
assert(false);
diff --git a/src/xact.cc b/src/xact.cc
index 68b607f4..f4331a29 100644
--- a/src/xact.cc
+++ b/src/xact.cc
@@ -560,4 +560,63 @@ void extend_xact_base(journal_t * journal,
xact->extend_xact(base, post_handler);
}
+void to_xml(std::ostream& out, const xact_t& xact)
+{
+ push_xml x(out, "transaction", true, true);
+
+ if (xact.state() == item_t::CLEARED)
+ out << " state=\"cleared\"";
+ else if (xact.state() == item_t::PENDING)
+ out << " state=\"pending\"";
+
+ if (xact.has_flags(ITEM_GENERATED))
+ out << " generated=\"true\"";
+
+ x.close_attrs();
+
+ if (xact._date) {
+ push_xml y(out, "date");
+ to_xml(out, *xact._date, false);
+ }
+ if (xact._date_eff) {
+ push_xml y(out, "effective-date");
+ to_xml(out, *xact._date_eff, false);
+ }
+
+ if (xact.code) {
+ push_xml y(out, "code");
+ out << y.guard(*xact.code);
+ }
+
+ {
+ push_xml y(out, "payee");
+ out << y.guard(xact.payee);
+ }
+
+ if (xact.note) {
+ push_xml y(out, "note");
+ out << y.guard(*xact.note);
+ }
+
+ if (xact.metadata) {
+ push_xml y(out, "metadata");
+ foreach (const item_t::string_map::value_type& pair, *xact.metadata) {
+ if (pair.second) {
+ push_xml z(out, "variable");
+ {
+ push_xml w(out, "key");
+ out << y.guard(pair.first);
+ }
+ {
+ push_xml w(out, "value");
+ out << y.guard(*pair.second);
+ }
+ } else {
+ push_xml z(out, "tag");
+ out << y.guard(pair.first);
+ }
+ }
+ }
+}
+
} // namespace ledger
diff --git a/src/xact.h b/src/xact.h
index 31422b3a..9a52fafe 100644
--- a/src/xact.h
+++ b/src/xact.h
@@ -289,6 +289,8 @@ typedef std::list<xact_t *> xacts_list;
typedef std::list<auto_xact_t *> auto_xacts_list;
typedef std::list<period_xact_t *> period_xacts_list;
+void to_xml(std::ostream& out, const xact_t& xact);
+
} // namespace ledger
#endif // _XACT_H
diff --git a/src/xml.cc b/src/xml.cc
index 02fa7137..9cff980a 100644
--- a/src/xml.cc
+++ b/src/xml.cc
@@ -72,39 +72,12 @@ namespace {
}
void xml_transaction(std::ostream& out, const xact_t * xact) {
- out << "<transaction>\n";
- out << "<payee>" << xact->payee << "</payee>\n";
+ to_xml(out, *xact);
- foreach (const post_t * post, xact->posts) {
+ foreach (const post_t * post, xact->posts)
if (post->has_xdata() &&
- post->xdata().has_flags(POST_EXT_VISITED)) {
- out << "<posting>\n";
- out << "<account ref=\"";
- out.width(sizeof(unsigned long) * 2);
- out.fill('0');
- out << std::hex << reinterpret_cast<unsigned long>(post->account);
- out << "\">" << post->account->fullname() << "</account>\n";
-
- out << "<quantity>\n";
- to_xml(out, post->amount);
- out << "</quantity>\n";
-
- out << "<cost>\n";
- if (post->cost)
- to_xml(out, *post->cost);
- else
- to_xml(out, post->amount);
- out << "</cost>\n";
-
- if (post->assigned_amount) {
- out << "<balance-assert>\n";
- to_xml(out, *post->assigned_amount);
- out << "</balance-assert>\n";
- }
-
- out << "</posting>\n";
- }
- }
+ post->xdata().has_flags(POST_EXT_VISITED))
+ to_xml(out, *post);
out << "</transaction>\n";
}
@@ -114,11 +87,12 @@ void format_xml::flush()
{
std::ostream& out(report.output_stream);
- out << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ledger>\n<journal>\n";
+ out << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
+ out << "<ledger version=\"" << VERSION << "\">\n";
out << "<commodities>\n";
foreach (const commodities_pair& pair, commodities) {
- to_xml(out, *pair.second);
+ to_xml(out, *pair.second, true);
out << '\n';
}
out << "</commodities>\n";
@@ -132,7 +106,7 @@ void format_xml::flush()
xml_transaction(out, xact);
out << "</transactions>\n";
- out << "</journal>\n</ledger>\n";
+ out << "</ledger>\n";
out.flush();
}