1 #include "ValuesFile.h"
3 #include "XMLHandler.h"
13 const char* const ANDROID_XMLNS = "http://schemas.android.com/apk/res/android";
14 const char* const XLIFF_XMLNS = "urn:oasis:names:tc:xliff:document:1.2";
16 const char *const NS_MAP[] = {
17 "android", ANDROID_XMLNS,
22 const XMLNamespaceMap ANDROID_NAMESPACES(NS_MAP);
25 // =====================================================================================
26 class ArrayHandler : public XMLHandler
29 ArrayHandler(ValuesFile* vf, int version, const string& versionString, const string& id);
31 virtual int OnStartElement(const SourcePos& pos, const string& ns, const string& name,
32 const vector<XMLAttribute>& attrs, XMLHandler** next);
33 virtual int OnText(const SourcePos& pos, const string& text);
34 virtual int OnComment(const SourcePos& pos, const string& text);
40 string m_versionString;
45 ArrayHandler::ArrayHandler(ValuesFile* vf, int version, const string& versionString,
50 m_versionString(versionString),
56 ArrayHandler::OnStartElement(const SourcePos& pos, const string& ns, const string& name,
57 const vector<XMLAttribute>& attrs, XMLHandler** next)
59 if (ns == "" && name == "item") {
60 XMLNode* node = XMLNode::NewElement(pos, ns, name, attrs, XMLNode::EXACT);
61 m_vf->AddString(StringResource(pos, pos.file, m_vf->GetConfiguration(),
62 m_id, m_index, node, m_version, m_versionString,
63 trim_string(m_comment)));
64 *next = new NodeHandler(node, XMLNode::EXACT);
69 pos.Error("invalid <%s> element inside <array>\n", name.c_str());
75 ArrayHandler::OnText(const SourcePos& pos, const string& text)
81 ArrayHandler::OnComment(const SourcePos& pos, const string& text)
87 // =====================================================================================
88 class ValuesHandler : public XMLHandler
91 ValuesHandler(ValuesFile* vf, int version, const string& versionString);
93 virtual int OnStartElement(const SourcePos& pos, const string& ns, const string& name,
94 const vector<XMLAttribute>& attrs, XMLHandler** next);
95 virtual int OnText(const SourcePos& pos, const string& text);
96 virtual int OnComment(const SourcePos& pos, const string& text);
101 string m_versionString;
105 ValuesHandler::ValuesHandler(ValuesFile* vf, int version, const string& versionString)
108 m_versionString(versionString)
113 ValuesHandler::OnStartElement(const SourcePos& pos, const string& ns, const string& name,
114 const vector<XMLAttribute>& attrs, XMLHandler** next)
116 if (ns == "" && name == "string") {
117 string id = XMLAttribute::Find(attrs, "", "name", "");
118 XMLNode* node = XMLNode::NewElement(pos, ns, name, attrs, XMLNode::EXACT);
119 m_vf->AddString(StringResource(pos, pos.file, m_vf->GetConfiguration(),
120 id, -1, node, m_version, m_versionString,
121 trim_string(m_comment)));
122 *next = new NodeHandler(node, XMLNode::EXACT);
124 else if (ns == "" && name == "array") {
125 string id = XMLAttribute::Find(attrs, "", "name", "");
126 *next = new ArrayHandler(m_vf, m_version, m_versionString, id);
133 ValuesHandler::OnText(const SourcePos& pos, const string& text)
139 ValuesHandler::OnComment(const SourcePos& pos, const string& text)
145 // =====================================================================================
146 ValuesFile::ValuesFile(const Configuration& config)
153 ValuesFile::~ValuesFile()
158 ValuesFile::ParseFile(const string& filename, const Configuration& config,
159 int version, const string& versionString)
161 ValuesFile* result = new ValuesFile(config);
163 TopElementHandler top("", "resources", new ValuesHandler(result, version, versionString));
164 XMLHandler::ParseFile(filename, &top);
170 ValuesFile::ParseString(const string& filename, const string& text, const Configuration& config,
171 int version, const string& versionString)
173 ValuesFile* result = new ValuesFile(config);
175 TopElementHandler top("", "resources", new ValuesHandler(result, version, versionString));
176 XMLHandler::ParseString(filename, text, &top);
182 ValuesFile::GetConfiguration() const
188 ValuesFile::AddString(const StringResource& str)
191 m_strings.insert(str);
193 m_arrays[str.id].insert(str);
198 ValuesFile::GetStrings() const
200 set<StringResource> result = m_strings;
202 for (map<string,set<StringResource> >::const_iterator it = m_arrays.begin();
203 it != m_arrays.end(); it++) {
204 result.insert(it->second.begin(), it->second.end());
211 ValuesFile::ToXMLNode() const
217 vector<XMLAttribute> attrs;
218 ANDROID_NAMESPACES.AddToAttributes(&attrs);
219 root = XMLNode::NewElement(GENERATED_POS, "", "resources", attrs, XMLNode::PRETTY);
223 for (map<string,set<StringResource> >::const_iterator it = m_arrays.begin();
224 it != m_arrays.end(); it++) {
225 vector<XMLAttribute> arrayAttrs;
226 arrayAttrs.push_back(XMLAttribute("", "name", it->first));
227 const set<StringResource>& items = it->second;
228 XMLNode* arrayNode = XMLNode::NewElement(items.begin()->pos, "", "array", arrayAttrs,
230 root->EditChildren().push_back(arrayNode);
233 for (set<StringResource>::const_iterator item = items.begin();
234 item != items.end(); item++) {
235 XMLNode* itemNode = item->value->Clone();
236 itemNode->SetName("", "item");
237 itemNode->EditAttributes().clear();
238 arrayNode->EditChildren().push_back(itemNode);
243 for (set<StringResource>::const_iterator it=m_strings.begin(); it!=m_strings.end(); it++) {
244 const StringResource& str = *it;
245 vector<XMLAttribute> attrs;
246 XMLNode* strNode = str.value->Clone();
247 strNode->SetName("", "string");
248 strNode->EditAttributes().clear();
249 strNode->EditAttributes().push_back(XMLAttribute("", "name", str.id));
250 root->EditChildren().push_back(strNode);
257 ValuesFile::ToString() const
259 XMLNode* xml = ToXMLNode();
260 string s = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
261 s += xml->ToString(ANDROID_NAMESPACES);