a73bbaf50dbae9975865753db8940b8895d2a56e
[vuplus_xbmc] / xbmc / utils / XMLUtils.cpp
1 /*
2  *      Copyright (C) 2005-2013 Team XBMC
3  *      http://xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include "XMLUtils.h"
22 #include "URL.h"
23 #include "StringUtils.h"
24 #ifdef TARGET_WINDOWS
25 #include "PlatformDefs.h" //for strcasecmp
26 #endif
27
28 bool XMLUtils::GetHex(const TiXmlNode* pRootNode, const char* strTag, uint32_t& hexValue)
29 {
30   const TiXmlNode* pNode = pRootNode->FirstChild(strTag );
31   if (!pNode || !pNode->FirstChild()) return false;
32   sscanf(pNode->FirstChild()->Value(), "%x", (uint32_t*) &hexValue );
33   return true;
34 }
35
36
37 bool XMLUtils::GetUInt(const TiXmlNode* pRootNode, const char* strTag, uint32_t& uintValue)
38 {
39   const TiXmlNode* pNode = pRootNode->FirstChild(strTag );
40   if (!pNode || !pNode->FirstChild()) return false;
41   uintValue = atol(pNode->FirstChild()->Value());
42   return true;
43 }
44
45 bool XMLUtils::GetUInt(const TiXmlNode* pRootNode, const char* strTag, uint32_t &value, const uint32_t min, const uint32_t max)
46 {
47   if (GetUInt(pRootNode, strTag, value))
48   {
49     if (value < min) value = min;
50     if (value > max) value = max;
51     return true;
52   }
53   return false;
54 }
55
56 bool XMLUtils::GetLong(const TiXmlNode* pRootNode, const char* strTag, long& lLongValue)
57 {
58   const TiXmlNode* pNode = pRootNode->FirstChild(strTag );
59   if (!pNode || !pNode->FirstChild()) return false;
60   lLongValue = atol(pNode->FirstChild()->Value());
61   return true;
62 }
63
64 bool XMLUtils::GetInt(const TiXmlNode* pRootNode, const char* strTag, int& iIntValue)
65 {
66   const TiXmlNode* pNode = pRootNode->FirstChild(strTag );
67   if (!pNode || !pNode->FirstChild()) return false;
68   iIntValue = atoi(pNode->FirstChild()->Value());
69   return true;
70 }
71
72 bool XMLUtils::GetInt(const TiXmlNode* pRootNode, const char* strTag, int &value, const int min, const int max)
73 {
74   if (GetInt(pRootNode, strTag, value))
75   {
76     if (value < min) value = min;
77     if (value > max) value = max;
78     return true;
79   }
80   return false;
81 }
82
83 bool XMLUtils::GetDouble(const TiXmlNode *root, const char *tag, double &value)
84 {
85   const TiXmlNode* node = root->FirstChild(tag);
86   if (!node || !node->FirstChild()) return false;
87   value = atof(node->FirstChild()->Value());
88   return true;
89 }
90
91 bool XMLUtils::GetFloat(const TiXmlNode* pRootNode, const char* strTag, float& value)
92 {
93   const TiXmlNode* pNode = pRootNode->FirstChild(strTag );
94   if (!pNode || !pNode->FirstChild()) return false;
95   value = (float)atof(pNode->FirstChild()->Value());
96   return true;
97 }
98
99 bool XMLUtils::GetFloat(const TiXmlNode* pRootElement, const char *tagName, float& fValue, const float fMin, const float fMax)
100 {
101   if (GetFloat(pRootElement, tagName, fValue))
102   { // check range
103     if (fValue < fMin) fValue = fMin;
104     if (fValue > fMax) fValue = fMax;
105     return true;
106   }
107   return false;
108 }
109
110 bool XMLUtils::GetBoolean(const TiXmlNode* pRootNode, const char* strTag, bool& bBoolValue)
111 {
112   const TiXmlNode* pNode = pRootNode->FirstChild(strTag );
113   if (!pNode || !pNode->FirstChild()) return false;
114   CStdString strEnabled = pNode->FirstChild()->Value();
115   strEnabled.ToLower();
116   if (strEnabled == "off" || strEnabled == "no" || strEnabled == "disabled" || strEnabled == "false" || strEnabled == "0" )
117     bBoolValue = false;
118   else
119   {
120     bBoolValue = true;
121     if (strEnabled != "on" && strEnabled != "yes" && strEnabled != "enabled" && strEnabled != "true")
122       return false; // invalid bool switch - it's probably some other string.
123   }
124   return true;
125 }
126
127 bool XMLUtils::GetString(const TiXmlNode* pRootNode, const char* strTag, CStdString& strStringValue)
128 {
129   std::string value;
130   if (GetString(pRootNode, strTag, value))
131   {
132     strStringValue = value;
133     return true;
134   }
135   return false;
136 }
137
138 bool XMLUtils::GetString(const TiXmlNode* pRootNode, const char* strTag, std::string& strStringValue)
139 {
140   const TiXmlElement* pElement = pRootNode->FirstChildElement(strTag );
141   if (!pElement) return false;
142   const char* encoded = pElement->Attribute("urlencoded");
143   const TiXmlNode* pNode = pElement->FirstChild();
144   if (pNode != NULL)
145   {
146     strStringValue = pNode->ValueStr();
147     if (encoded && strcasecmp(encoded,"yes") == 0)
148       strStringValue = CURL::Decode(strStringValue);
149     return true;
150   }
151   strStringValue.clear();
152   return true;
153 }
154
155 bool XMLUtils::HasChild(const TiXmlNode* pRootNode, const char* strTag)
156 {
157   const TiXmlElement* pElement = pRootNode->FirstChildElement(strTag);
158   if (!pElement) return false;
159   const TiXmlNode* pNode = pElement->FirstChild();
160   return (pNode != NULL);
161 }
162
163 bool XMLUtils::GetAdditiveString(const TiXmlNode* pRootNode, const char* strTag,
164                                  const CStdString& strSeparator, CStdString& strStringValue,
165                                  bool clear)
166 {
167   CStdString strTemp;
168   const TiXmlElement* node = pRootNode->FirstChildElement(strTag);
169   bool bResult=false;
170   if (node && node->FirstChild() && clear)
171     strStringValue.clear();
172   while (node)
173   {
174     if (node->FirstChild())
175     {
176       bResult = true;
177       strTemp = node->FirstChild()->Value();
178       const char* clear=node->Attribute("clear");
179       if (strStringValue.IsEmpty() || (clear && strcasecmp(clear,"true")==0))
180         strStringValue = strTemp;
181       else
182         strStringValue += strSeparator+strTemp;
183     }
184     node = node->NextSiblingElement(strTag);
185   }
186
187   return bResult;
188 }
189
190 /*!
191   Parses the XML for multiple tags of the given name.
192   Does not clear the array to support chaining.
193 */
194 bool XMLUtils::GetStringArray(const TiXmlNode* pRootNode, const char* strTag, std::vector<std::string>& arrayValue, bool clear /* = false */, const std::string separator /* = "" */)
195 {
196   std::string strTemp;
197   const TiXmlElement* node = pRootNode->FirstChildElement(strTag);
198   bool bResult=false;
199   if (node && node->FirstChild() && clear)
200     arrayValue.clear();
201   while (node)
202   {
203     if (node->FirstChild())
204     {
205       bResult = true;
206       strTemp = node->FirstChild()->ValueStr();
207
208       const char* clearAttr = node->Attribute("clear");
209       if (clearAttr && strcasecmp(clearAttr, "true") == 0)
210         arrayValue.clear();
211
212       if (strTemp.empty())
213         continue;
214
215       if (separator.empty())
216         arrayValue.push_back(strTemp);
217       else
218       {
219         std::vector<std::string> tempArray = StringUtils::Split(strTemp, separator);
220         arrayValue.insert(arrayValue.end(), tempArray.begin(), tempArray.end());
221       }
222     }
223     node = node->NextSiblingElement(strTag);
224   }
225
226   return bResult;
227 }
228
229 /*!
230   Returns true if the encoding of the document is other then UTF-8.
231   /param strEncoding Returns the encoding of the document. Empty if UTF-8
232 */
233 bool XMLUtils::GetEncoding(const CXBMCTinyXML* pDoc, CStdString& strEncoding)
234 {
235   const TiXmlNode* pNode=NULL;
236   while ((pNode=pDoc->IterateChildren(pNode)) && pNode->Type()!=TiXmlNode::TINYXML_DECLARATION) {}
237   if (!pNode) return false;
238   const TiXmlDeclaration* pDecl=pNode->ToDeclaration();
239   if (!pDecl) return false;
240   strEncoding=pDecl->Encoding();
241   if (strEncoding.Equals("UTF-8") || strEncoding.Equals("UTF8")) strEncoding.Empty();
242   strEncoding.MakeUpper();
243   return !strEncoding.IsEmpty(); // Other encoding then UTF8?
244 }
245
246 /*!
247   Returns true if the encoding of the document is specified as as UTF-8
248   /param strXML The XML file (embedded in a string) to check.
249 */
250 bool XMLUtils::HasUTF8Declaration(const CStdString &strXML)
251 {
252   CStdString test = strXML;
253   test.ToLower();
254   // test for the encoding="utf-8" string
255   if (test.Find("encoding=\"utf-8\"") >= 0)
256     return true;
257   // TODO: test for plain UTF8 here?
258   return false;
259 }
260
261 bool XMLUtils::GetPath(const TiXmlNode* pRootNode, const char* strTag, CStdString& strStringValue)
262 {
263   const TiXmlElement* pElement = pRootNode->FirstChildElement(strTag);
264   if (!pElement) return false;
265
266   const char* encoded = pElement->Attribute("urlencoded");
267   const TiXmlNode* pNode = pElement->FirstChild();
268   if (pNode != NULL)
269   {
270     strStringValue = pNode->Value();
271     if (encoded && strcasecmp(encoded,"yes") == 0)
272       CURL::Decode(strStringValue);
273     return true;
274   }
275   strStringValue.Empty();
276   return false;
277 }
278
279 bool XMLUtils::GetDate(const TiXmlNode* pRootNode, const char* strTag, CDateTime& date)
280 {
281   CStdString strDate;
282   if (GetString(pRootNode, strTag, strDate) && !strDate.empty())
283   {
284     date.SetFromDBDate(strDate);
285     return true;
286   }
287
288   return false;
289 }
290
291 bool XMLUtils::GetDateTime(const TiXmlNode* pRootNode, const char* strTag, CDateTime& dateTime)
292 {
293   CStdString strDateTime;
294   if (GetString(pRootNode, strTag, strDateTime) && !strDateTime.empty())
295   {
296     dateTime.SetFromDBDateTime(strDateTime);
297     return true;
298   }
299
300   return false;
301 }
302
303 void XMLUtils::SetAdditiveString(TiXmlNode* pRootNode, const char *strTag, const CStdString& strSeparator, const CStdString& strValue)
304 {
305   CStdStringArray list;
306   StringUtils::SplitString(strValue,strSeparator,list);
307   for (unsigned int i=0;i<list.size() && !list[i].IsEmpty();++i)
308     SetString(pRootNode,strTag,list[i]);
309 }
310
311 void XMLUtils::SetStringArray(TiXmlNode* pRootNode, const char *strTag, const std::vector<std::string>& arrayValue)
312 {
313   for (unsigned int i = 0; i < arrayValue.size(); i++)
314     SetString(pRootNode, strTag, arrayValue.at(i));
315 }
316
317 void XMLUtils::SetString(TiXmlNode* pRootNode, const char *strTag, const CStdString& strValue)
318 {
319   TiXmlElement newElement(strTag);
320   TiXmlNode *pNewNode = pRootNode->InsertEndChild(newElement);
321   if (pNewNode)
322   {
323     TiXmlText value(strValue);
324     pNewNode->InsertEndChild(value);
325   }
326 }
327
328 void XMLUtils::SetInt(TiXmlNode* pRootNode, const char *strTag, int value)
329 {
330   CStdString strValue;
331   strValue.Format("%i", value);
332   SetString(pRootNode, strTag, strValue);
333 }
334
335 void XMLUtils::SetLong(TiXmlNode* pRootNode, const char *strTag, long value)
336 {
337   CStdString strValue;
338   strValue.Format("%ld", value);
339   SetString(pRootNode, strTag, strValue);
340 }
341
342 void XMLUtils::SetFloat(TiXmlNode* pRootNode, const char *strTag, float value)
343 {
344   CStdString strValue;
345   strValue.Format("%f", value);
346   SetString(pRootNode, strTag, strValue);
347 }
348
349 void XMLUtils::SetBoolean(TiXmlNode* pRootNode, const char *strTag, bool value)
350 {
351   SetString(pRootNode, strTag, value ? "true" : "false");
352 }
353
354 void XMLUtils::SetHex(TiXmlNode* pRootNode, const char *strTag, uint32_t value)
355 {
356   CStdString strValue;
357   strValue.Format("%x", value);
358   SetString(pRootNode, strTag, strValue);
359 }
360
361 void XMLUtils::SetPath(TiXmlNode* pRootNode, const char *strTag, const CStdString& strValue)
362 {
363   TiXmlElement newElement(strTag);
364   newElement.SetAttribute("pathversion", path_version);
365   TiXmlNode *pNewNode = pRootNode->InsertEndChild(newElement);
366   if (pNewNode)
367   {
368     TiXmlText value(strValue);
369     pNewNode->InsertEndChild(value);
370   }
371 }
372
373 void XMLUtils::SetDate(TiXmlNode* pRootNode, const char *strTag, const CDateTime& date)
374 {
375   SetString(pRootNode, strTag, date.GetAsDBDate());
376 }
377
378 void XMLUtils::SetDateTime(TiXmlNode* pRootNode, const char *strTag, const CDateTime& dateTime)
379 {
380   SetString(pRootNode, strTag, dateTime.GetAsDBDateTime());
381 }