Add setters to XMLFeature.

This commit is contained in:
Sergey Magidovich 2015-12-01 17:12:29 +03:00 committed by Sergey Yershov
parent 0e38939461
commit 4d4d5e235b
3 changed files with 180 additions and 99 deletions

View file

@ -8,76 +8,85 @@
#include "std/sstream.hpp"
// UNIT_TEST(FeatureFromXml)
// {
// auto const featureXml = R"(
// <node id="1107716196" visible="true" version="5" changeset="7864398"
// timestamp="2011-04-14T19:51:12Z" user="Amigo" uid="206282"
// lat="55.7978998" lon="37.4745280">
// <tag k="historic" v="memorial"/>
// <tag k="name" v="Памятник В.И. Ленину"/>
// </node>)";
// pugi::xml_document doc;
// auto const result = doc.load_string(featureXml);
// TEST(result, (result.description()));
// }
using namespace indexer;
// UNIT_TEST(FeatureToXml)
// {
// XMLFeature feature;
// feature.SetModificationTime(my::StringToTimestamp("2015-11-27T21:13:32Z"));
UNIT_TEST(XMLFeature_RawGetSet)
{
XMLFeature feature;
TEST(!feature.HasTag("opening_hours"), ());
TEST(!feature.HasAttribute("center"), ());
// feature.SetCenter({64.234234, 53.31242});
// feature.SetTagValue("opening_hours", "Mo-Fr 08:15-17:30");
feature.SetAttribute("FooBar", "foobar");
TEST_EQUAL(feature.GetAttribute("FooBar"), "foobar", ());
// feature.SetInterationalName("Gorki Park");
feature.SetAttribute("FooBar", "foofoo");
TEST_EQUAL(feature.GetAttribute("FooBar"), "foofoo", ());
// StringUtf8Multilang names;
// names.AddString("en", "Gorki Park");
// names.AddString("ru", "Парк Горького");
feature.SetTagValue("opening_hours", "18:20-18:21");
TEST_EQUAL(feature.GetTagValue("opening_hours"), "18:20-18:21", ());
// feature.SetMultilungName(names);
feature.SetTagValue("opening_hours", "18:20-19:21");
TEST_EQUAL(feature.GetTagValue("opening_hours"), "18:20-19:21", ());
// StringNumericOptimal house;
// house.Set(10);
// feature.SetHouse(house);
auto const expected = R"(<?xml version="1.0"?>
<node
FooBar="foofoo">
<tag
k="opening_hours"
v="18:20-19:21" />
</node>
)";
// pugi::xml_document document;
// feature.ToXMLDocument(document);
// stringstream sstr;
// document.save(sstr, "\t", pugi::format_indent_attributes);
// auto const expectedString = R"(<?xml version="1.0"?>
// <node
// center="64.234234000000000719, 53.312420000000003029"
// timestamp="2015-11-27T21:13:32Z">
// <tag
// k="name"
// v="Gorki Park" />
// <tag
// k="name::en"
// v="Gorki Park" />
// <tag
// k="name::ru"
// v="Парк Горького" />
// <tag
// k="addr:housenumber"
// v="10" />
// <tag
// k="opening_hours"
// v="Mo-Fr 08:15-17:30" />
// </node>
// )";
// TEST_EQUAL(sstr.str(), expectedString, ());
// }
stringstream sstr;
feature.Save(sstr);
TEST_EQUAL(expected, sstr.str(), ());
}
UNIT_TEST(FeatureFromXml)
UNIT_TEST(XMLFeature_Setters)
{
XMLFeature feature;
feature.SetCenter(m2::PointD(64.2342340, 53.3124200));
feature.SetModificationTime(my::StringToTimestamp("2015-11-27T21:13:32Z"));
feature.SetName("Gorki Park");
feature.SetName("en", "Gorki Park");
feature.SetName("ru", "Парк Горького");
feature.SetHouse("10");
feature.SetTagValue("opening_hours", "Mo-Fr 08:15-17:30");
stringstream sstr;
feature.Save(sstr);
auto const expectedString = R"(<?xml version="1.0"?>
<node
center="64.2342340, 53.3124200"
timestamp="2015-11-27T21:13:32Z">
<tag
k="name"
v="Gorki Park" />
<tag
k="name:en"
v="Gorki Park" />
<tag
k="name:ru"
v="Парк Горького" />
<tag
k="addr:housenumber"
v="10" />
<tag
k="opening_hours"
v="Mo-Fr 08:15-17:30" />
</node>
)";
TEST_EQUAL(sstr.str(), expectedString, ());
}
UNIT_TEST(XMLFeatureFromXml)
{
auto const srcString = R"(<?xml version="1.0"?>
<node
@ -87,10 +96,10 @@ UNIT_TEST(FeatureFromXml)
k="name"
v="Gorki Park" />
<tag
k="name::en"
k="name:en"
v="Gorki Park" />
<tag
k="name::ru"
k="name:ru"
v="Парк Горького" />
<tag
k="addr:housenumber"
@ -104,11 +113,12 @@ UNIT_TEST(FeatureFromXml)
XMLFeature feature(srcString);
stringstream sstr;
feature.GetXMLDocument().save(sstr, "\t", pugi::format_indent_attributes);
feature.Save(sstr);
TEST_EQUAL(srcString, sstr.str(), ());
TEST(feature.HasTag("opening_hours"), ());
TEST(!feature.HasTag("FooBarBaz"), ());
TEST(feature.HasKey("opening_hours"), ());
TEST(feature.HasKey("center"), ());
TEST(!feature.HasKey("FooBarBaz"), ());
TEST_EQUAL(feature.GetHouse(), "10", ());
TEST_EQUAL(feature.GetCenter(), m2::PointD(64.2342340, 53.3124200), ());

View file

@ -13,6 +13,7 @@ namespace
string ToString(m2::PointD const & p)
{
ostringstream out;
out << fixed;
out.precision(7);
out << p.x << ", " << p.y;
return out.str();
@ -30,23 +31,19 @@ bool FromString(string const & str, m2::PointD & p)
return true;
}
void AddTag(string const & key, string const & value, pugi::xml_node & node)
pugi::xml_node FindTag(pugi::xml_document const & document, string const & key)
{
auto tag = node.append_child("tag");
tag.append_attribute("k") = key.data();
tag.append_attribute("v") = value.data();
}
pugi::xpath_node FindTag(pugi::xml_document const & document, string const & key)
{
return document.select_node(("//tag[@k='" + key + "']").data());
return document.select_node(("//tag[@k='" + key + "']").data()).node();
}
} // namespace
namespace indexer
{
XMLFeature::XMLFeature(): m_documentPtr(new pugi::xml_document) {}
XMLFeature::XMLFeature(): m_documentPtr(new pugi::xml_document)
{
m_documentPtr->append_child("node");
}
XMLFeature::XMLFeature(string const & xml):
XMLFeature()
@ -69,9 +66,15 @@ XMLFeature::XMLFeature(string const & xml):
MYTHROW(XMLFeatureError, ("Node has no timestamp attribute"));
}
pugi::xml_document const & XMLFeature::GetXMLDocument() const
XMLFeature::XMLFeature(pugi::xml_document const & xml):
XMLFeature()
{
return *m_documentPtr;
m_documentPtr->reset(xml);
}
void XMLFeature::Save(ostream & ost) const
{
m_documentPtr->save(ost, "\t", pugi::format_indent_attributes);
}
m2::PointD XMLFeature::GetCenter() const
@ -82,9 +85,14 @@ m2::PointD XMLFeature::GetCenter() const
return center;
}
void XMLFeature::SetCenter(m2::PointD const & center)
{
SetAttribute("center", ToString(center));
}
string const XMLFeature::GetName(string const & lang) const
{
auto const suffix = lang == "default" || lang.empty() ? "" : "::" + lang;
auto const suffix = lang == "default" || lang.empty() ? "" : ":" + lang;
return GetTagValue("name" + suffix);
}
@ -93,49 +101,95 @@ string const XMLFeature::GetName(uint8_t const langCode) const
return GetName(StringUtf8Multilang::GetLangByCode(langCode));
}
void XMLFeature::SetName(string const & name)
{
SetName("default", name);
}
void XMLFeature::SetName(string const & lang, string const & name)
{
auto const suffix = lang == "default" || lang.empty() ? "" : ":" + lang;
SetTagValue("name" + suffix, name);
}
void XMLFeature::SetName(uint8_t const langCode, string const & name)
{
SetName(StringUtf8Multilang::GetLangByCode(langCode), name);
}
string const XMLFeature::GetHouse() const
{
return GetTagValue("addr:housenumber");
}
void XMLFeature::SetHouse(string const & house)
{
SetTagValue("addr:housenumber", house);
}
time_t XMLFeature::GetModificationTime() const
{
auto const node = m_documentPtr->child("node");
return my::StringToTimestamp(node.attribute("timestamp").value());
}
void XMLFeature::SetModificationTime(time_t const time)
{
SetAttribute("timestamp", my::TimestampToString(time));
}
bool XMLFeature::HasTag(string const & key) const
{
return FindTag(*m_documentPtr, key);
}
bool XMLFeature::HasAttribute(string const & key) const
{
return GetRootNode().attribute(key.data());
}
bool XMLFeature::HasKey(string const & key) const
{
return HasTag(key) || HasAttribute(key);
}
string XMLFeature::GetTagValue(string const & key) const
{
auto const tag = FindTag(*m_documentPtr, key);
return tag.node().attribute("v").value();
return tag.attribute("v").value();
}
// bool XMLFeature::ToXMLDocument(pugi::xml_document & document) const
// {
// auto node = document.append_child("node");
// node.append_attribute("center") = ToString(GetCenter()).data();
// node.append_attribute("timestamp") = my::TimestampToString(GetModificationTime()).data();
void XMLFeature::SetTagValue(string const & key, string const value)
{
auto tag = FindTag(*m_documentPtr, key);
if (!tag)
{
tag = GetRootNode().append_child("tag");
tag.append_attribute("k") = key.data();
tag.append_attribute("v") = value.data();
}
else
{
tag.attribute("v") = value.data();
}
}
// AddTag("name", GetInternationalName(), node);
string XMLFeature::GetAttribute(string const & key) const
{
return GetRootNode().attribute(key.data()).value();
}
// GetMultilangName().ForEachRef([&node](int8_t lang, string const & name) {
// AddTag("name::" + string(StringUtf8Multilang::GetLangByCode(lang)), name, node);
// return true;
// });
// if (!GetHouse().Get().empty())
// AddTag("addr:housenumber", GetHouse().Get(), node);
// for (auto const & tag : m_tags)
// AddTag(tag.first, tag.second, node);
// return true;
// }
void XMLFeature::SetAttribute(string const & key, string const & value)
{
auto node = HasAttribute(key)
? GetRootNode().attribute(key.data())
: GetRootNode().append_attribute(key.data());
node = value.data();
}
pugi::xml_node XMLFeature::GetRootNode() const
{
return m_documentPtr->child("node");
}
} // namespace indexer

View file

@ -6,13 +6,14 @@
#include "coding/value_opt_string.hpp"
#include "std/ctime.hpp"
#include "std/iostream.hpp"
#include "std/map.hpp"
#include "std/unique_ptr.hpp"
namespace pugi
{
class xml_document;
class xml_node;
}
namespace indexer
@ -25,23 +26,39 @@ class XMLFeature
public:
XMLFeature();
XMLFeature(string const & xml);
XMLFeature(pugi::xml_document const & xml);
pugi::xml_document const & GetXMLDocument() const;
void Save(ostream & ost) const;
m2::PointD GetCenter() const;
void SetCenter(m2::PointD const & center);
string const GetName(string const & lang = "") const;
string const GetName(uint8_t const langCode) const;
void SetName(string const & name);
void SetName(string const & lang, string const & name);
void SetName(uint8_t const langCode, string const & name);
string const GetHouse() const;
void SetHouse(string const & house);
time_t GetModificationTime() const;
void SetModificationTime(time_t const time);
bool HasTag(string const & key) const;
bool HasAttribute(string const & key) const;
bool HasKey(string const & key) const;
string GetTagValue(string const & key) const;
void SetTagValue(string const & key, string const value);
string GetAttribute(string const & key) const;
void SetAttribute(string const & key, string const & value);
private:
pugi::xml_node GetRootNode() const;
unique_ptr<pugi::xml_document> m_documentPtr;
};
} // namespace indexer