fix ledger xml output, remove ledger json command

As the format used by property trees to represent valid JSON
and that for valid XML is too different and given that there are
more requests for valid XML output I decided to pursue a quick fix
and remove the json command in favor of a working xml command.

See bug #782, #909, recent discussion on mailing list.

JSON support is postponed until I or someone else finds time to work on
this or the python bindings are more stable.
This commit is contained in:
Johann Klähn 2013-03-08 21:45:56 +01:00
parent 8f4b0e8962
commit a875940a93
16 changed files with 68 additions and 121 deletions

View file

@ -692,12 +692,10 @@ void account_t::xdata_t::details_t::update(post_t& post,
}
}
void put_account(property_tree::ptree& pt, const account_t& acct,
void put_account(property_tree::ptree& st, const account_t& acct,
function<bool(const account_t&)> pred)
{
if (pred(acct)) {
property_tree::ptree& st(pt.put("account", ""));
std::ostringstream buf;
buf.width(sizeof(unsigned long) * 2);
buf.fill('0');
@ -709,18 +707,15 @@ void put_account(property_tree::ptree& pt, const account_t& acct,
st.put("fullname", acct.fullname());
value_t total = acct.amount();
if (! total.is_null()) {
property_tree::ptree& t(st.put("account-amount", ""));
put_value(t, total);
}
if (! total.is_null())
put_value(st.put("account-amount", ""), total);
total = acct.total();
if (! total.is_null()) {
property_tree::ptree& t(st.put("account-total", ""));
put_value(t, total);
}
if (! total.is_null())
put_value(st.put("account-total", ""), total);
foreach (const accounts_map::value_type& pair, acct.accounts)
put_account(st, *pair.second, pred);
put_account(st.add("account", ""), *pair.second, pred);
}
}

View file

@ -1320,13 +1320,11 @@ bool amount_t::valid() const
return true;
}
void put_amount(property_tree::ptree& pt, const amount_t& amt,
bool wrap, bool commodity_details)
void put_amount(property_tree::ptree& st, const amount_t& amt,
bool commodity_details)
{
property_tree::ptree& st(wrap ? pt.put("amount", "") : pt);
if (amt.has_commodity())
put_commodity(st, amt.commodity(), commodity_details);
put_commodity(st.put("commodity", ""), amt.commodity(), commodity_details);
st.put("quantity", amt.quantity_string());
}

View file

@ -793,7 +793,7 @@ inline std::istream& operator>>(std::istream& in, amount_t& amt) {
}
void put_amount(property_tree::ptree& pt, const amount_t& amt,
bool wrap = true, bool commodity_details = false);
bool commodity_details = false);
} // namespace ledger

View file

@ -216,19 +216,13 @@ void annotation_t::print(std::ostream& out, bool keep_base,
out << " ((" << *value_expr << "))";
}
void put_annotation(property_tree::ptree& pt, const annotation_t& details)
void put_annotation(property_tree::ptree& st, const annotation_t& details)
{
property_tree::ptree& st(pt.put("annotation", ""));
if (details.price)
put_amount(st.put("price", ""), *details.price);
if (details.price) {
property_tree::ptree& t(st.put("price", ""));
put_amount(t, *details.price, false);
}
if (details.date) {
property_tree::ptree& t(st.put("date", ""));
put_date(t, *details.date, false);
}
if (details.date)
put_date(st.put("date", ""), *details.date);
if (details.tag)
st.put("tag", *details.tag);

View file

@ -336,12 +336,10 @@ void balance_t::print(std::ostream& out,
amount_printer.close();
}
void put_balance(property_tree::ptree& pt, const balance_t& bal)
void put_balance(property_tree::ptree& st, const balance_t& bal)
{
property_tree::ptree& st(pt.put("balance", ""));
foreach (const balance_t::amounts_map::value_type& pair, bal.amounts)
put_amount(st, pair.second);
put_amount(st.add("amount", ""), pair.second);
}
} // namespace ledger

View file

@ -497,11 +497,9 @@ bool commodity_t::compare_by_commodity::operator()(const amount_t * left,
}
}
void put_commodity(property_tree::ptree& pt, const commodity_t& comm,
void put_commodity(property_tree::ptree& st, const commodity_t& comm,
bool commodity_details)
{
property_tree::ptree& st(pt.put("commodity", ""));
std::string flags;
if (! (comm.has_flags(COMMODITY_STYLE_SUFFIXED))) flags += 'P';
if (comm.has_flags(COMMODITY_STYLE_SEPARATED)) flags += 'S';
@ -512,7 +510,7 @@ void put_commodity(property_tree::ptree& pt, const commodity_t& comm,
st.put("symbol", comm.symbol());
if (commodity_details && comm.has_annotation())
put_annotation(st, as_annotated_commodity(comm).details);
put_annotation(st.put("annotation", ""), as_annotated_commodity(comm).details);
}
} // namespace ledger

View file

@ -600,16 +600,15 @@ string item_context(const item_t& item, const string& desc)
return out.str();
}
void put_metadata(property_tree::ptree& pt, const item_t::string_map& metadata)
void put_metadata(property_tree::ptree& st, const item_t::string_map& metadata)
{
property_tree::ptree& st(pt.put("metadata", ""));
foreach (const item_t::string_map::value_type& pair, metadata) {
if (pair.second.first) {
property_tree::ptree& vt(st.put("pair", ""));
vt.put("key", pair.first);
property_tree::ptree& vt(st.add("value", ""));
vt.put("<xmlattr>.key", pair.first);
put_value(vt, *pair.second.first);
} else {
st.put("tag", pair.first);
st.add("tag", pair.first);
}
}
}

View file

@ -151,7 +151,7 @@ inline std::ostream& operator<<(std::ostream& out, const mask_t& mask) {
}
inline void put_mask(property_tree::ptree& pt, const mask_t& mask) {
pt.put("mask", mask.str());
pt.put_value(mask.str());
}
} // namespace ledger

View file

@ -696,10 +696,8 @@ void extend_post(post_t& post, journal_t& journal)
}
}
void put_post(property_tree::ptree& pt, const post_t& post)
void put_post(property_tree::ptree& st, const post_t& post)
{
property_tree::ptree& st(pt.put("posting", ""));
if (post.state() == item_t::CLEARED)
st.put("<xmlattr>.state", "cleared");
else if (post.state() == item_t::PENDING)
@ -710,14 +708,10 @@ void put_post(property_tree::ptree& pt, const post_t& post)
if (post.has_flags(ITEM_GENERATED))
st.put("<xmlattr>.generated", "true");
if (post._date) {
property_tree::ptree& t(st.put("date", ""));
put_date(t, *post._date, false);
}
if (post._date_aux) {
property_tree::ptree& t(st.put("aux-date", ""));
put_date(t, *post._date_aux, false);
}
if (post._date)
put_date(st.put("date", ""), *post._date);
if (post._date_aux)
put_date(st.put("aux-date", ""), *post._date_aux);
if (post.account) {
property_tree::ptree& t(st.put("account", ""));
@ -736,34 +730,27 @@ void put_post(property_tree::ptree& pt, const post_t& post)
if (post.has_xdata() && post.xdata().has_flags(POST_EXT_COMPOUND))
put_value(t, post.xdata().compound_value);
else
put_amount(t, post.amount);
put_amount(t.put("amount", ""), post.amount);
}
if (post.cost) {
property_tree::ptree& t(st.put("cost", ""));
put_amount(t, *post.cost, false);
}
if (post.cost)
put_amount(st.put("cost", ""), *post.cost);
if (post.assigned_amount) {
if (post.has_flags(POST_CALCULATED)) {
property_tree::ptree& t(st.put("balance-assertion", ""));
put_amount(t, *post.assigned_amount, false);
} else {
property_tree::ptree& t(st.put("balance-assignment", ""));
put_amount(t, *post.assigned_amount, false);
}
if (post.has_flags(POST_CALCULATED))
put_amount(st.put("balance-assertion", ""), *post.assigned_amount);
else
put_amount(st.put("balance-assignment", ""), *post.assigned_amount);
}
if (post.note)
st.put("note", *post.note);
if (post.metadata)
put_metadata(st, *post.metadata);
put_metadata(st.put("metadata", ""), *post.metadata);
if (post.xdata_ && ! post.xdata_->total.is_null()) {
property_tree::ptree& t(st.put("total", ""));
put_value(t, post.xdata_->total);
}
if (post.xdata_ && ! post.xdata_->total.is_null())
put_value(st.put("total", ""), post.xdata_->total);
}
} // namespace ledger

View file

@ -61,28 +61,27 @@ void format_ptree::flush()
property_tree::ptree& ct(pt.put("ledger.commodities", ""));
foreach (const commodities_pair& pair, commodities)
put_commodity(ct, *pair.second, true);
put_commodity(ct.add("commodity", ""), *pair.second, true);
property_tree::ptree& at(pt.put("ledger.accounts", ""));
put_account(at, *report.session.journal->master, account_visited_p);
put_account(at.add("account", ""), *report.session.journal->master, account_visited_p);
property_tree::ptree& tt(pt.put("ledger.transactions", ""));
foreach (const xact_t * xact, transactions) {
put_xact(tt, *xact);
property_tree::ptree& t(tt.add("transaction", ""));
put_xact(t, *xact);
property_tree::ptree& post_tree(tt.put("postings", ""));
property_tree::ptree& post_tree(t.put("postings", ""));
foreach (const post_t * post, xact->posts)
if (post->has_xdata() &&
post->xdata().has_flags(POST_EXT_VISITED))
put_post(post_tree, *post);
put_post(post_tree.add("posting", ""), *post);
}
switch (format) {
case FORMAT_XML:
property_tree::write_xml(out, pt);
break;
case FORMAT_JSON:
property_tree::write_json(out, pt);
out << std::endl;
break;
}
}

View file

@ -75,8 +75,7 @@ protected:
public:
enum format_t {
FORMAT_XML,
FORMAT_JSON
FORMAT_XML
} format;
format_ptree(report_t& _report, format_t _format = FORMAT_XML)

View file

@ -1628,11 +1628,6 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind,
}
break;
case 'j':
if (is_eq(p, "json"))
return POSTS_REPORTER(new format_ptree(*this,
format_ptree::FORMAT_JSON));
break;
case 'l':
if (is_eq(p, "lisp"))
return POSTS_REPORTER(new format_emacs_posts(output_stream));

View file

@ -204,7 +204,6 @@ typedef std::ostream::pos_type ostream_pos_type;
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int.hpp>

View file

@ -111,20 +111,12 @@ 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 put_datetime(property_tree::ptree& pt, const datetime_t& when,
bool wrap = true) {
if (wrap)
pt.put("datetime", format_datetime(when, FMT_WRITTEN));
else
pt.put_value(format_datetime(when, FMT_WRITTEN));
inline void put_datetime(property_tree::ptree& pt, const datetime_t& when) {
pt.put_value(format_datetime(when, FMT_WRITTEN));
}
inline void put_date(property_tree::ptree& pt, const date_t& when,
bool wrap = true) {
if (wrap)
pt.put("date", format_date(when, FMT_WRITTEN));
else
pt.put_value(format_date(when, FMT_WRITTEN));
inline void put_date(property_tree::ptree& pt, const date_t& when) {
pt.put_value(format_date(when, FMT_WRITTEN));
}
struct date_traits_t

View file

@ -2062,35 +2062,35 @@ void put_value(property_tree::ptree& pt, const value_t& value)
{
switch (value.type()) {
case value_t::VOID:
pt.put("void", "");
pt.add("void", "");
break;
case value_t::BOOLEAN:
pt.put("bool", value.as_boolean() ? "true" : "false");
pt.add("bool", value.as_boolean() ? "true" : "false");
break;
case value_t::INTEGER:
pt.put("int", value.to_string());
pt.add("int", value.to_string());
break;
case value_t::AMOUNT:
put_amount(pt, value.as_amount());
put_amount(pt.add("amount", ""), value.as_amount());
break;
case value_t::BALANCE:
put_balance(pt, value.as_balance());
put_balance(pt.add("balance", ""), value.as_balance());
break;
case value_t::DATETIME:
put_datetime(pt, value.as_datetime());
put_datetime(pt.add("datetime", ""), value.as_datetime());
break;
case value_t::DATE:
put_date(pt, value.as_date());
put_date(pt.add("date", ""), value.as_date());
break;
case value_t::STRING:
pt.put("string", value.as_string());
pt.add("string", value.as_string());
break;
case value_t::MASK:
put_mask(pt, value.as_mask());
put_mask(pt.add("mask", ""), value.as_mask());
break;
case value_t::SEQUENCE: {
property_tree::ptree& st(pt.put("sequence", ""));
property_tree::ptree& st(pt.add("sequence", ""));
foreach (const value_t& member, value.as_sequence())
put_value(st, member);
break;

View file

@ -847,10 +847,8 @@ void auto_xact_t::extend_xact(xact_base_t& xact, parse_context_t& context)
}
}
void put_xact(property_tree::ptree& pt, const xact_t& xact)
void put_xact(property_tree::ptree& st, const xact_t& xact)
{
property_tree::ptree& st(pt.put("transaction", ""));
if (xact.state() == item_t::CLEARED)
st.put("<xmlattr>.state", "cleared");
else if (xact.state() == item_t::PENDING)
@ -859,14 +857,10 @@ void put_xact(property_tree::ptree& pt, const xact_t& xact)
if (xact.has_flags(ITEM_GENERATED))
st.put("<xmlattr>.generated", "true");
if (xact._date) {
property_tree::ptree& t(st.put("date", ""));
put_date(t, *xact._date, false);
}
if (xact._date_aux) {
property_tree::ptree& t(st.put("aux-date", ""));
put_date(t, *xact._date_aux, false);
}
if (xact._date)
put_date(st.put("date", ""), *xact._date);
if (xact._date_aux)
put_date(st.put("aux-date", ""), *xact._date_aux);
if (xact.code)
st.put("code", *xact.code);
@ -877,7 +871,7 @@ void put_xact(property_tree::ptree& pt, const xact_t& xact)
st.put("note", *xact.note);
if (xact.metadata)
put_metadata(st, *xact.metadata);
put_metadata(st.put("metadata", ""), *xact.metadata);
}
} // namespace ledger