1 // 2 // Copyright (c) 2008-2017 the Urho3D project. 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a copy 5 // of this software and associated documentation files (the "Software"), to deal 6 // in the Software without restriction, including without limitation the rights 7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 // copies of the Software, and to permit persons to whom the Software is 9 // furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 // THE SOFTWARE. 21 // 22 23 #pragma once 24 25 #include "../Container/Ptr.h" 26 #include "../Core/Variant.h" 27 #include "../Math/BoundingBox.h" 28 #include "../Math/Rect.h" 29 30 namespace pugi 31 { 32 33 struct xml_node_struct; 34 class xpath_node; 35 class xpath_node_set; 36 class xpath_query; 37 class xpath_variable_set; 38 39 } 40 41 namespace Urho3D 42 { 43 44 class XMLFile; 45 class XPathQuery; 46 class XPathResultSet; 47 48 /// Element in an XML file. 49 class URHO3D_API XMLElement 50 { 51 public: 52 /// Construct null element. 53 XMLElement(); 54 /// Construct with document and node pointers. 55 XMLElement(XMLFile* file, pugi::xml_node_struct* node); 56 /// Construct from xpath query result set. 57 XMLElement(XMLFile* file, const XPathResultSet* resultSet, const pugi::xpath_node* xpathNode, unsigned xpathResultIndex); 58 /// Copy-construct from another element. 59 XMLElement(const XMLElement& rhs); 60 /// Destruct. 61 ~XMLElement(); 62 /// Assignment operator. 63 XMLElement& operator =(const XMLElement& rhs); 64 65 /// Create a child element. 66 XMLElement CreateChild(const String& name); 67 /// Create a child element. 68 XMLElement CreateChild(const char* name); 69 /// Return the first child element with name or create if does not exist. 70 XMLElement GetOrCreateChild(const String& name); 71 /// Return the first child element with name or create if does not exist. 72 XMLElement GetOrCreateChild(const char* name); 73 /// Remove a child element. Return true if successful. 74 bool RemoveChild(const XMLElement& element); 75 /// Remove a child element by name. Return true if successful. 76 bool RemoveChild(const String& name); 77 /// Remove a child element by name. Return true if successful. 78 bool RemoveChild(const char* name); 79 /// Remove child elements of certain name, or all child elements if name is empty. Return true if successful. 80 bool RemoveChildren(const String& name = String::EMPTY); 81 /// Remove child elements of certain name, or all child elements if name is empty. Return true if successful. 82 bool RemoveChildren(const char* name); 83 /// Remove an attribute by name. Return true if successful. 84 bool RemoveAttribute(const String& name = String::EMPTY); 85 /// Remove an attribute by name. Return true if successful. 86 bool RemoveAttribute(const char* name); 87 88 /// Select an element/attribute using XPath query. 89 XMLElement SelectSingle(const String& query, pugi::xpath_variable_set* variables = 0) const; 90 /// Select an element/attribute using XPath query. 91 XMLElement SelectSinglePrepared(const XPathQuery& query) const; 92 /// Select elements/attributes using XPath query. 93 XPathResultSet Select(const String& query, pugi::xpath_variable_set* variables = 0) const; 94 /// Select elements/attributes using XPath query. 95 XPathResultSet SelectPrepared(const XPathQuery& query) const; 96 97 /// Set the value for an inner node in the following format <node>value</node>. 98 bool SetValue(const String& value); 99 /// Set the value for an inner node in the following format <node>value</node>. Must be used on the <node> element. 100 bool SetValue(const char* value); 101 /// Set an attribute. 102 bool SetAttribute(const String& name, const String& value); 103 /// Set an attribute. 104 bool SetAttribute(const char* name, const char* value); 105 /// Set an attribute. Only valid if it is an attribute only XPath query result. 106 bool SetAttribute(const String& value); 107 /// Set an attribute. Only valid if it is an attribute only XPath query result. 108 bool SetAttribute(const char* value); 109 /// Set a bool attribute. 110 bool SetBool(const String& name, bool value); 111 /// Set a BoundingBox attribute. 112 bool SetBoundingBox(const BoundingBox& value); 113 /// Set a buffer attribute. 114 bool SetBuffer(const String& name, const void* data, unsigned size); 115 /// Set a buffer attribute. 116 bool SetBuffer(const String& name, const PODVector<unsigned char>& value); 117 /// Set a color attribute. 118 bool SetColor(const String& name, const Color& value); 119 /// Set a float attribute. 120 bool SetFloat(const String& name, float value); 121 /// Set a double attribute. 122 bool SetDouble(const String& name, double value); 123 /// Set an unsigned integer attribute. 124 bool SetUInt(const String& name, unsigned value); 125 /// Set an integer attribute. 126 bool SetInt(const String& name, int value); 127 /// Set an unsigned long long integer attribute. 128 bool SetUInt64(const String& name, unsigned long long value); 129 /// Set a long long integer attribute. 130 bool SetInt64(const String& name, long long value); 131 /// Set an IntRect attribute. 132 bool SetIntRect(const String& name, const IntRect& value); 133 /// Set an IntVector2 attribute. 134 bool SetIntVector2(const String& name, const IntVector2& value); 135 /// Set an IntVector3 attribute. 136 bool SetIntVector3(const String& name, const IntVector3& value); 137 /// Set a Rect attribute. 138 bool SetRect(const String& name, const Rect& value); 139 /// Set a quaternion attribute. 140 bool SetQuaternion(const String& name, const Quaternion& value); 141 /// Set a string attribute. 142 bool SetString(const String& name, const String& value); 143 /// Set a variant attribute. 144 bool SetVariant(const Variant& value); 145 /// Set a variant attribute excluding the type. 146 bool SetVariantValue(const Variant& value); 147 /// Set a resource reference attribute. 148 bool SetResourceRef(const ResourceRef& value); 149 /// Set a resource reference list attribute. 150 bool SetResourceRefList(const ResourceRefList& value); 151 /// Set a variant vector attribute. Creates child elements as necessary. 152 bool SetVariantVector(const VariantVector& value); 153 /// Set a string vector attribute. Creates child elements as necessary. 154 bool SetStringVector(const StringVector& value); 155 /// Set a variant map attribute. Creates child elements as necessary. 156 bool SetVariantMap(const VariantMap& value); 157 /// Set a Vector2 attribute. 158 bool SetVector2(const String& name, const Vector2& value); 159 /// Set a Vector3 attribute. 160 bool SetVector3(const String& name, const Vector3& value); 161 /// Set a Vector4 attribute. 162 bool SetVector4(const String& name, const Vector4& value); 163 /// Set a float, Vector or Matrix attribute stored in a variant. 164 bool SetVectorVariant(const String& name, const Variant& value); 165 /// Set a Matrix3 attribute. 166 bool SetMatrix3(const String& name, const Matrix3& value); 167 /// Set a Matrix3x4 attribute. 168 bool SetMatrix3x4(const String& name, const Matrix3x4& value); 169 /// Set a Matrix4 attribute. 170 bool SetMatrix4(const String& name, const Matrix4& value); 171 172 /// Return whether does not refer to an element or an XPath node. 173 bool IsNull() const; 174 /// Return whether refers to an element or an XPath node. 175 bool NotNull() const; 176 /// Return true if refers to an element or an XPath node. 177 operator bool() const; 178 /// Return element name (or attribute name if it is an attribute only XPath query result). 179 String GetName() const; 180 /// Return whether has a child element. 181 bool HasChild(const String& name) const; 182 /// Return whether has a child element. 183 bool HasChild(const char* name) const; 184 /// Return child element, or null if missing. 185 XMLElement GetChild(const String& name = String::EMPTY) const; 186 /// Return child element, or null if missing. 187 XMLElement GetChild(const char* name) const; 188 /// Return next sibling element. 189 XMLElement GetNext(const String& name = String::EMPTY) const; 190 /// Return next sibling element. 191 XMLElement GetNext(const char* name) const; 192 /// Return parent element. 193 XMLElement GetParent() const; 194 /// Return number of attributes. 195 unsigned GetNumAttributes() const; 196 /// Return whether has an attribute. 197 bool HasAttribute(const String& name) const; 198 /// Return whether has an attribute. 199 bool HasAttribute(const char* name) const; 200 /// Return inner value, or empty if missing for nodes like <node>value</node> 201 String GetValue() const; 202 /// Return attribute, or empty if missing. 203 String GetAttribute(const String& name = String::EMPTY) const; 204 /// Return attribute, or empty if missing. 205 String GetAttribute(const char* name) const; 206 /// Return attribute as C string, or null if missing. 207 const char* GetAttributeCString(const char* name) const; 208 /// Return attribute in lowercase, or empty if missing. 209 String GetAttributeLower(const String& name) const; 210 /// Return attribute in lowercase, or empty if missing. 211 String GetAttributeLower(const char* name) const; 212 /// Return attribute in lowercase, or empty if missing. 213 String GetAttributeUpper(const String& name) const; 214 /// Return attribute in lowercase, or empty if missing. 215 String GetAttributeUpper(const char* name) const; 216 /// Return names of all attributes. 217 Vector<String> GetAttributeNames() const; 218 /// Return bool attribute, or false if missing. 219 bool GetBool(const String& name) const; 220 /// Return buffer attribute, or empty if missing. 221 PODVector<unsigned char> GetBuffer(const String& name) const; 222 /// Copy buffer attribute into a supplied buffer. Return true if buffer was large enough. 223 bool GetBuffer(const String& name, void* dest, unsigned size) const; 224 /// Return bounding box attribute, or empty if missing. 225 BoundingBox GetBoundingBox() const; 226 /// Return a color attribute, or default if missing. 227 Color GetColor(const String& name) const; 228 /// Return a float attribute, or zero if missing. 229 float GetFloat(const String& name) const; 230 /// Return a double attribute, or zero if missing. 231 double GetDouble(const String& name) const; 232 /// Return an unsigned integer attribute, or zero if missing. 233 unsigned GetUInt(const String& name) const; 234 /// Return an integer attribute, or zero if missing. 235 int GetInt(const String& name) const; 236 /// Return an unsigned long long integer attribute, or zero if missing. 237 unsigned long long GetUInt64(const String& name) const; 238 /// Return a long long integer attribute, or zero if missing. 239 long long GetInt64(const String& name) const; 240 /// Return an IntRect attribute, or default if missing. 241 IntRect GetIntRect(const String& name) const; 242 /// Return an IntVector2 attribute, or default if missing. 243 IntVector2 GetIntVector2(const String& name) const; 244 /// Return an IntVector3 attribute, or default if missing. 245 IntVector3 GetIntVector3(const String& name) const; 246 /// Return a Rect attribute, or default if missing. 247 Rect GetRect(const String& name) const; 248 /// Return a quaternion attribute, or default if missing. 249 Quaternion GetQuaternion(const String& name) const; 250 /// Return a variant attribute, or empty if missing. 251 Variant GetVariant() const; 252 /// Return a variant attribute with static type. 253 Variant GetVariantValue(VariantType type) const; 254 /// Return a resource reference attribute, or empty if missing. 255 ResourceRef GetResourceRef() const; 256 /// Return a resource reference list attribute, or empty if missing. 257 ResourceRefList GetResourceRefList() const; 258 /// Return a variant vector attribute, or empty if missing. 259 VariantVector GetVariantVector() const; 260 /// Return a string vector attribute, or empty if missing. 261 StringVector GetStringVector() const; 262 /// Return a variant map attribute, or empty if missing. 263 VariantMap GetVariantMap() const; 264 /// Return a Vector2 attribute, or zero vector if missing. 265 Vector2 GetVector2(const String& name) const; 266 /// Return a Vector3 attribute, or zero vector if missing. 267 Vector3 GetVector3(const String& name) const; 268 /// Return a Vector4 attribute, or zero vector if missing. 269 Vector4 GetVector4(const String& name) const; 270 /// Return any Vector attribute as Vector4. Missing coordinates will be zero. 271 Vector4 GetVector(const String& name) const; 272 /// Return a float, Vector or Matrix attribute as Variant. 273 Variant GetVectorVariant(const String& name) const; 274 /// Return a Matrix3 attribute, or zero matrix if missing. 275 Matrix3 GetMatrix3(const String& name) const; 276 /// Return a Matrix3x4 attribute, or zero matrix if missing. 277 Matrix3x4 GetMatrix3x4(const String& name) const; 278 /// Return a Matrix4 attribute, or zero matrix if missing. 279 Matrix4 GetMatrix4(const String& name) const; 280 /// Return XML file. 281 XMLFile* GetFile() const; 282 283 /// Return pugixml xml_node_struct. GetNode()284 pugi::xml_node_struct* GetNode() const { return node_; } 285 286 /// Return XPath query result set. GetXPathResultSet()287 const XPathResultSet* GetXPathResultSet() const { return xpathResultSet_; } 288 289 /// Return pugixml xpath_node. GetXPathNode()290 const pugi::xpath_node* GetXPathNode() const { return xpathNode_; } 291 292 /// Return current result index. GetXPathResultIndex()293 unsigned GetXPathResultIndex() const { return xpathResultIndex_; } 294 295 /// Return next XPath query result. Only valid when this instance of XMLElement is itself one of the query result in the result set. 296 XMLElement NextResult() const; 297 298 /// Empty XMLElement. 299 static const XMLElement EMPTY; 300 301 private: 302 /// XML file. 303 WeakPtr<XMLFile> file_; 304 /// Pugixml node. 305 pugi::xml_node_struct* node_; 306 /// XPath query result set. 307 const XPathResultSet* xpathResultSet_; 308 /// Pugixml xpath_node. 309 const pugi::xpath_node* xpathNode_; 310 /// Current XPath query result index (used internally to advance to subsequent query result). 311 mutable unsigned xpathResultIndex_; 312 }; 313 314 /// XPath query result set. 315 class URHO3D_API XPathResultSet 316 { 317 public: 318 /// Construct empty result set. 319 XPathResultSet(); 320 /// Construct with result set from XPath query. 321 XPathResultSet(XMLFile* file, pugi::xpath_node_set* resultSet); 322 /// Copy-construct. 323 XPathResultSet(const XPathResultSet& rhs); 324 /// Destruct. 325 ~XPathResultSet(); 326 /// Assignment operator. 327 XPathResultSet& operator =(const XPathResultSet& rhs); 328 /// Return the n-th result in the set. Call XMLElement::GetNextResult() to get the subsequent result in the set. 329 /// Note: The XPathResultSet return value must be stored in a lhs variable to ensure the underlying xpath_node_set* is still valid while performing XPathResultSet::FirstResult(), XPathResultSet::operator [], and XMLElement::NextResult(). 330 XMLElement operator [](unsigned index) const; 331 /// Return the first result in the set. Call XMLElement::GetNextResult() to get the subsequent result in the set. 332 /// Note: The XPathResultSet return value must be stored in a lhs variable to ensure the underlying xpath_node_set* is still valid while performing XPathResultSet::FirstResult(), XPathResultSet::operator [], and XMLElement::NextResult(). 333 XMLElement FirstResult(); 334 /// Return size of result set. 335 unsigned Size() const; 336 /// Return whether result set is empty. 337 bool Empty() const; 338 339 /// Return pugixml xpath_node_set. GetXPathNodeSet()340 pugi::xpath_node_set* GetXPathNodeSet() const { return resultSet_; } 341 342 private: 343 /// XML file. 344 WeakPtr<XMLFile> file_; 345 /// Pugixml xpath_node_set. 346 pugi::xpath_node_set* resultSet_; 347 }; 348 349 /// XPath query. 350 class URHO3D_API XPathQuery 351 { 352 public: 353 /// Construct empty. 354 XPathQuery(); 355 /// Construct XPath query object with query string and variable string. The variable string format is "name1:type1,name2:type2,..." where type is one of "Bool", "Float", "String", "ResultSet". 356 XPathQuery(const String& queryString, const String& variableString = String::EMPTY); 357 /// Destruct. 358 ~XPathQuery(); 359 /// Bind query object with variable set. 360 void Bind(); 361 /// Add/Set a bool variable. Return true if successful. 362 bool SetVariable(const String& name, bool value); 363 /// Add/Set a float variable. Return true if successful. 364 bool SetVariable(const String& name, float value); 365 /// Add/Set a string variable. Return true if successful. 366 bool SetVariable(const String& name, const String& value); 367 /// Add/Set a string variable. Return true if successful. 368 bool SetVariable(const char* name, const char* value); 369 /// Add/Set an XPath query result set variable. Return true if successful. 370 bool SetVariable(const String& name, const XPathResultSet& value); 371 /// Set XPath query string and variable string. The variable string format is "name1:type1,name2:type2,..." where type is one of "Bool", "Float", "String", "ResultSet". 372 bool SetQuery(const String& queryString, const String& variableString = String::EMPTY, bool bind = true); 373 /// Clear by removing all variables and XPath query object. 374 void Clear(); 375 /// Evaluate XPath query and expecting a boolean return value. 376 bool EvaluateToBool(XMLElement element) const; 377 /// Evaluate XPath query and expecting a float return value. 378 float EvaluateToFloat(XMLElement element) const; 379 /// Evaluate XPath query and expecting a string return value. 380 String EvaluateToString(XMLElement element) const; 381 /// Evaluate XPath query and expecting an XPath query result set as return value. 382 /// Note: The XPathResultSet return value must be stored in a lhs variable to ensure the underlying xpath_node_set* is still valid while performing XPathResultSet::FirstResult(), XPathResultSet::operator [], and XMLElement::NextResult(). 383 XPathResultSet Evaluate(XMLElement element) const; 384 385 /// Return query string. GetQuery()386 String GetQuery() const { return queryString_; } 387 388 /// Return pugixml xpath_query. GetXPathQuery()389 pugi::xpath_query* GetXPathQuery() const { return query_.Get(); } 390 391 /// Return pugixml xpath_variable_set. GetXPathVariableSet()392 pugi::xpath_variable_set* GetXPathVariableSet() const { return variables_.Get(); } 393 394 private: 395 /// XPath query string. 396 String queryString_; 397 /// Pugixml xpath_query. 398 UniquePtr<pugi::xpath_query> query_; 399 /// Pugixml xpath_variable_set. 400 UniquePtr<pugi::xpath_variable_set> variables_; 401 }; 402 403 } 404