2 * Copyright (C) 2005-2013 Team XBMC
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)
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.
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/>.
23 #include "StringUtils.h"
25 #include "PlatformDefs.h" //for strcasecmp
28 bool XMLUtils::GetHex(const TiXmlNode* pRootNode, const char* strTag, uint32_t& hexValue)
30 const TiXmlNode* pNode = pRootNode->FirstChild(strTag );
31 if (!pNode || !pNode->FirstChild()) return false;
32 sscanf(pNode->FirstChild()->Value(), "%x", (uint32_t*) &hexValue );
37 bool XMLUtils::GetUInt(const TiXmlNode* pRootNode, const char* strTag, uint32_t& uintValue)
39 const TiXmlNode* pNode = pRootNode->FirstChild(strTag );
40 if (!pNode || !pNode->FirstChild()) return false;
41 uintValue = atol(pNode->FirstChild()->Value());
45 bool XMLUtils::GetUInt(const TiXmlNode* pRootNode, const char* strTag, uint32_t &value, const uint32_t min, const uint32_t max)
47 if (GetUInt(pRootNode, strTag, value))
49 if (value < min) value = min;
50 if (value > max) value = max;
56 bool XMLUtils::GetLong(const TiXmlNode* pRootNode, const char* strTag, long& lLongValue)
58 const TiXmlNode* pNode = pRootNode->FirstChild(strTag );
59 if (!pNode || !pNode->FirstChild()) return false;
60 lLongValue = atol(pNode->FirstChild()->Value());
64 bool XMLUtils::GetInt(const TiXmlNode* pRootNode, const char* strTag, int& iIntValue)
66 const TiXmlNode* pNode = pRootNode->FirstChild(strTag );
67 if (!pNode || !pNode->FirstChild()) return false;
68 iIntValue = atoi(pNode->FirstChild()->Value());
72 bool XMLUtils::GetInt(const TiXmlNode* pRootNode, const char* strTag, int &value, const int min, const int max)
74 if (GetInt(pRootNode, strTag, value))
76 if (value < min) value = min;
77 if (value > max) value = max;
83 bool XMLUtils::GetDouble(const TiXmlNode *root, const char *tag, double &value)
85 const TiXmlNode* node = root->FirstChild(tag);
86 if (!node || !node->FirstChild()) return false;
87 value = atof(node->FirstChild()->Value());
91 bool XMLUtils::GetFloat(const TiXmlNode* pRootNode, const char* strTag, float& value)
93 const TiXmlNode* pNode = pRootNode->FirstChild(strTag );
94 if (!pNode || !pNode->FirstChild()) return false;
95 value = (float)atof(pNode->FirstChild()->Value());
99 bool XMLUtils::GetFloat(const TiXmlNode* pRootElement, const char *tagName, float& fValue, const float fMin, const float fMax)
101 if (GetFloat(pRootElement, tagName, fValue))
103 if (fValue < fMin) fValue = fMin;
104 if (fValue > fMax) fValue = fMax;
110 bool XMLUtils::GetBoolean(const TiXmlNode* pRootNode, const char* strTag, bool& bBoolValue)
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" )
121 if (strEnabled != "on" && strEnabled != "yes" && strEnabled != "enabled" && strEnabled != "true")
122 return false; // invalid bool switch - it's probably some other string.
127 bool XMLUtils::GetString(const TiXmlNode* pRootNode, const char* strTag, CStdString& strStringValue)
130 if (GetString(pRootNode, strTag, value))
132 strStringValue = value;
138 bool XMLUtils::GetString(const TiXmlNode* pRootNode, const char* strTag, std::string& strStringValue)
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();
146 strStringValue = pNode->ValueStr();
147 if (encoded && strcasecmp(encoded,"yes") == 0)
148 strStringValue = CURL::Decode(strStringValue);
151 strStringValue.clear();
155 bool XMLUtils::HasChild(const TiXmlNode* pRootNode, const char* strTag)
157 const TiXmlElement* pElement = pRootNode->FirstChildElement(strTag);
158 if (!pElement) return false;
159 const TiXmlNode* pNode = pElement->FirstChild();
160 return (pNode != NULL);
163 bool XMLUtils::GetAdditiveString(const TiXmlNode* pRootNode, const char* strTag,
164 const CStdString& strSeparator, CStdString& strStringValue,
168 const TiXmlElement* node = pRootNode->FirstChildElement(strTag);
170 if (node && node->FirstChild() && clear)
171 strStringValue.clear();
174 if (node->FirstChild())
177 strTemp = node->FirstChild()->Value();
178 const char* clear=node->Attribute("clear");
179 if (strStringValue.IsEmpty() || (clear && strcasecmp(clear,"true")==0))
180 strStringValue = strTemp;
182 strStringValue += strSeparator+strTemp;
184 node = node->NextSiblingElement(strTag);
191 Parses the XML for multiple tags of the given name.
192 Does not clear the array to support chaining.
194 bool XMLUtils::GetStringArray(const TiXmlNode* pRootNode, const char* strTag, std::vector<std::string>& arrayValue, bool clear /* = false */, const std::string separator /* = "" */)
197 const TiXmlElement* node = pRootNode->FirstChildElement(strTag);
199 if (node && node->FirstChild() && clear)
203 if (node->FirstChild())
206 strTemp = node->FirstChild()->ValueStr();
208 const char* clearAttr = node->Attribute("clear");
209 if (clearAttr && strcasecmp(clearAttr, "true") == 0)
215 if (separator.empty())
216 arrayValue.push_back(strTemp);
219 std::vector<std::string> tempArray = StringUtils::Split(strTemp, separator);
220 arrayValue.insert(arrayValue.end(), tempArray.begin(), tempArray.end());
223 node = node->NextSiblingElement(strTag);
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
233 bool XMLUtils::GetEncoding(const CXBMCTinyXML* pDoc, CStdString& strEncoding)
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?
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.
250 bool XMLUtils::HasUTF8Declaration(const CStdString &strXML)
252 CStdString test = strXML;
254 // test for the encoding="utf-8" string
255 if (test.Find("encoding=\"utf-8\"") >= 0)
257 // TODO: test for plain UTF8 here?
261 bool XMLUtils::GetPath(const TiXmlNode* pRootNode, const char* strTag, CStdString& strStringValue)
263 const TiXmlElement* pElement = pRootNode->FirstChildElement(strTag);
264 if (!pElement) return false;
266 const char* encoded = pElement->Attribute("urlencoded");
267 const TiXmlNode* pNode = pElement->FirstChild();
270 strStringValue = pNode->Value();
271 if (encoded && strcasecmp(encoded,"yes") == 0)
272 CURL::Decode(strStringValue);
275 strStringValue.Empty();
279 bool XMLUtils::GetDate(const TiXmlNode* pRootNode, const char* strTag, CDateTime& date)
282 if (GetString(pRootNode, strTag, strDate) && !strDate.empty())
284 date.SetFromDBDate(strDate);
291 bool XMLUtils::GetDateTime(const TiXmlNode* pRootNode, const char* strTag, CDateTime& dateTime)
293 CStdString strDateTime;
294 if (GetString(pRootNode, strTag, strDateTime) && !strDateTime.empty())
296 dateTime.SetFromDBDateTime(strDateTime);
303 void XMLUtils::SetAdditiveString(TiXmlNode* pRootNode, const char *strTag, const CStdString& strSeparator, const CStdString& strValue)
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]);
311 void XMLUtils::SetStringArray(TiXmlNode* pRootNode, const char *strTag, const std::vector<std::string>& arrayValue)
313 for (unsigned int i = 0; i < arrayValue.size(); i++)
314 SetString(pRootNode, strTag, arrayValue.at(i));
317 void XMLUtils::SetString(TiXmlNode* pRootNode, const char *strTag, const CStdString& strValue)
319 TiXmlElement newElement(strTag);
320 TiXmlNode *pNewNode = pRootNode->InsertEndChild(newElement);
323 TiXmlText value(strValue);
324 pNewNode->InsertEndChild(value);
328 void XMLUtils::SetInt(TiXmlNode* pRootNode, const char *strTag, int value)
331 strValue.Format("%i", value);
332 SetString(pRootNode, strTag, strValue);
335 void XMLUtils::SetLong(TiXmlNode* pRootNode, const char *strTag, long value)
338 strValue.Format("%ld", value);
339 SetString(pRootNode, strTag, strValue);
342 void XMLUtils::SetFloat(TiXmlNode* pRootNode, const char *strTag, float value)
345 strValue.Format("%f", value);
346 SetString(pRootNode, strTag, strValue);
349 void XMLUtils::SetBoolean(TiXmlNode* pRootNode, const char *strTag, bool value)
351 SetString(pRootNode, strTag, value ? "true" : "false");
354 void XMLUtils::SetHex(TiXmlNode* pRootNode, const char *strTag, uint32_t value)
357 strValue.Format("%x", value);
358 SetString(pRootNode, strTag, strValue);
361 void XMLUtils::SetPath(TiXmlNode* pRootNode, const char *strTag, const CStdString& strValue)
363 TiXmlElement newElement(strTag);
364 newElement.SetAttribute("pathversion", path_version);
365 TiXmlNode *pNewNode = pRootNode->InsertEndChild(newElement);
368 TiXmlText value(strValue);
369 pNewNode->InsertEndChild(value);
373 void XMLUtils::SetDate(TiXmlNode* pRootNode, const char *strTag, const CDateTime& date)
375 SetString(pRootNode, strTag, date.GetAsDBDate());
378 void XMLUtils::SetDateTime(TiXmlNode* pRootNode, const char *strTag, const CDateTime& dateTime)
380 SetString(pRootNode, strTag, dateTime.GetAsDBDateTime());