forked from organicmaps/organicmaps
Add setters to XMLFeature.
This commit is contained in:
parent
0e38939461
commit
4d4d5e235b
3 changed files with 180 additions and 99 deletions
|
@ -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), ());
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue