XmlNode.cpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. /*
  2. * Author: Patrick-Christopher Mattulat
  3. * Company: Lynar Studios
  4. * E-Mail: webmaster@lynarstudios.com
  5. * Created: 2020-09-24
  6. * Changed: 2023-02-06
  7. *
  8. * */
  9. #include <algorithm>
  10. #include <ls-std/core/exception/IllegalArgumentException.hpp>
  11. #include <ls-std/io/xml/XmlNode.hpp>
  12. ls::std::io::XmlNode::XmlNode(::std::string _name) : ls::std::core::Class("XmlNode"), name(::std::move(_name))
  13. {}
  14. ls::std::io::XmlNode::~XmlNode() = default;
  15. bool ls::std::io::XmlNode::addAttributeAfter(const ::std::shared_ptr<ls::std::io::XmlAttribute> &_attribute, const ::std::string &_name)
  16. {
  17. bool added{};
  18. auto iterator = this->attributes.begin();
  19. _checkIfAttributeReferenceIsValid(_attribute);
  20. _checkIfNameIsNotEmpty(_name);
  21. if (!this->_hasAttribute(_attribute->getName()))
  22. {
  23. while (iterator != this->attributes.end())
  24. {
  25. if ((*iterator)->getName() == _name)
  26. {
  27. iterator++;
  28. this->attributes.insert(iterator, _attribute);
  29. added = true;
  30. break;
  31. }
  32. iterator++;
  33. }
  34. }
  35. return added;
  36. }
  37. bool ls::std::io::XmlNode::addAttributeBefore(const ::std::shared_ptr<ls::std::io::XmlAttribute> &_attribute, const ::std::string &_name)
  38. {
  39. bool added{};
  40. auto iterator = this->attributes.begin();
  41. _checkIfAttributeReferenceIsValid(_attribute);
  42. _checkIfNameIsNotEmpty(_name);
  43. if (!this->_hasAttribute(_attribute->getName()))
  44. {
  45. while (iterator != this->attributes.end())
  46. {
  47. if ((*iterator)->getName() == _name)
  48. {
  49. this->attributes.insert(iterator, _attribute);
  50. added = true;
  51. break;
  52. }
  53. iterator++;
  54. }
  55. }
  56. return added;
  57. }
  58. bool ls::std::io::XmlNode::addAttributeToBeginning(const ::std::shared_ptr<ls::std::io::XmlAttribute> &_attribute)
  59. {
  60. bool added{};
  61. _checkIfAttributeReferenceIsValid(_attribute);
  62. if (!_hasAttribute(_attribute->getName()))
  63. {
  64. this->attributes.push_front(_attribute);
  65. added = true;
  66. }
  67. return added;
  68. }
  69. bool ls::std::io::XmlNode::addAttributeToEnd(const ::std::shared_ptr<ls::std::io::XmlAttribute> &_attribute)
  70. {
  71. bool added{};
  72. _checkIfAttributeReferenceIsValid(_attribute);
  73. if (!_hasAttribute(_attribute->getName()))
  74. {
  75. this->attributes.push_back(_attribute);
  76. added = true;
  77. }
  78. return added;
  79. }
  80. bool ls::std::io::XmlNode::addChildAfter(const ::std::shared_ptr<ls::std::io::XmlNode> &_child, const ::std::shared_ptr<ls::std::io::XmlNode> &_search)
  81. {
  82. bool added{};
  83. auto iterator = this->children.begin();
  84. _checkIfNodeReferenceIsValid(_child);
  85. _checkIfNodeReferenceIsValid(_search);
  86. if (!this->_hasChild(_child))
  87. {
  88. while (iterator != this->children.end())
  89. {
  90. if (*iterator == _search)
  91. {
  92. iterator++;
  93. this->children.insert(iterator, _child);
  94. added = true;
  95. break;
  96. }
  97. iterator++;
  98. }
  99. }
  100. return added;
  101. }
  102. bool ls::std::io::XmlNode::addChildBefore(const ::std::shared_ptr<ls::std::io::XmlNode> &_child, const ::std::shared_ptr<ls::std::io::XmlNode> &_search)
  103. {
  104. bool added{};
  105. auto iterator = this->children.begin();
  106. _checkIfNodeReferenceIsValid(_child);
  107. _checkIfNodeReferenceIsValid(_search);
  108. if (!this->_hasChild(_child))
  109. {
  110. while (iterator != this->children.end())
  111. {
  112. if (*iterator == _search)
  113. {
  114. this->children.insert(iterator, _child);
  115. added = true;
  116. break;
  117. }
  118. iterator++;
  119. }
  120. }
  121. return added;
  122. }
  123. bool ls::std::io::XmlNode::addChildToBeginning(const ::std::shared_ptr<ls::std::io::XmlNode> &_child)
  124. {
  125. bool added{};
  126. _checkIfNodeReferenceIsValid(_child);
  127. if (!this->_hasChild(_child))
  128. {
  129. this->children.push_front(_child);
  130. added = true;
  131. }
  132. return added;
  133. }
  134. bool ls::std::io::XmlNode::addChildToEnd(const ::std::shared_ptr<ls::std::io::XmlNode> &_child)
  135. {
  136. bool added{};
  137. _checkIfNodeReferenceIsValid(_child);
  138. if (!this->_hasChild(_child))
  139. {
  140. this->children.push_back(_child);
  141. added = true;
  142. }
  143. return added;
  144. }
  145. void ls::std::io::XmlNode::clearValue()
  146. {
  147. this->value.clear();
  148. }
  149. std::list<std::shared_ptr<ls::std::io::XmlAttribute>> ls::std::io::XmlNode::getAttributes()
  150. {
  151. return this->attributes;
  152. }
  153. std::list<std::shared_ptr<ls::std::io::XmlNode>> ls::std::io::XmlNode::getChildren()
  154. {
  155. return this->children;
  156. }
  157. std::list<std::shared_ptr<ls::std::io::XmlNode>> ls::std::io::XmlNode::getChildren(const ::std::string &_name)
  158. {
  159. ::std::list<::std::shared_ptr<ls::std::io::XmlNode>> childrenWithName{};
  160. for (const auto &child : this->children)
  161. {
  162. if (child->getName() == _name)
  163. {
  164. childrenWithName.push_back(child);
  165. }
  166. }
  167. return childrenWithName;
  168. }
  169. std::string ls::std::io::XmlNode::getName()
  170. {
  171. return this->name;
  172. }
  173. std::string ls::std::io::XmlNode::getValue()
  174. {
  175. return this->value;
  176. }
  177. bool ls::std::io::XmlNode::hasAttribute(const ::std::string &_name)
  178. {
  179. return this->_hasAttribute(_name);
  180. }
  181. bool ls::std::io::XmlNode::hasChild(const ::std::string &_name)
  182. {
  183. return this->_hasChild(_name);
  184. }
  185. bool ls::std::io::XmlNode::hasChild(const ::std::shared_ptr<ls::std::io::XmlNode> &_child)
  186. {
  187. return this->_hasChild(_child);
  188. }
  189. bool ls::std::io::XmlNode::removeFirstAttribute()
  190. {
  191. bool isValidOperation = !this->attributes.empty();
  192. if (isValidOperation)
  193. {
  194. this->attributes.pop_front();
  195. }
  196. return isValidOperation;
  197. }
  198. bool ls::std::io::XmlNode::removeLastAttribute()
  199. {
  200. bool isValidOperation = !this->attributes.empty();
  201. if (isValidOperation)
  202. {
  203. this->attributes.pop_back();
  204. }
  205. return isValidOperation;
  206. }
  207. bool ls::std::io::XmlNode::removeFirstChild()
  208. {
  209. bool isValidOperation = !this->children.empty();
  210. if (isValidOperation)
  211. {
  212. this->children.pop_front();
  213. }
  214. return isValidOperation;
  215. }
  216. bool ls::std::io::XmlNode::removeLastChild()
  217. {
  218. bool isValidOperation = !this->children.empty();
  219. if (isValidOperation)
  220. {
  221. this->children.pop_back();
  222. }
  223. return isValidOperation;
  224. }
  225. void ls::std::io::XmlNode::setName(const ::std::string &_name)
  226. {
  227. this->_assignName(_name);
  228. }
  229. void ls::std::io::XmlNode::setValue(const ::std::string &_value)
  230. {
  231. this->_assignValue(_value);
  232. }
  233. std::string ls::std::io::XmlNode::toXml()
  234. {
  235. return this->_toXml_(0);
  236. }
  237. std::string ls::std::io::XmlNode::_toXml_(uint8_t _tabSize)
  238. {
  239. ::std::string xmlStream{};
  240. xmlStream += ls::std::io::XmlNode::_getTab(_tabSize);
  241. xmlStream += this->_toXmlOpenTag();
  242. xmlStream += this->_toXmlAttributes();
  243. xmlStream += this->_toXmlOpenTagClose();
  244. xmlStream += this->_toXmlValue();
  245. xmlStream += this->_toXmlChildren(_tabSize + TAB_SIZE);
  246. xmlStream += this->value.empty() ? ls::std::io::XmlNode::_getTab(_tabSize) : "";
  247. xmlStream += this->_toXmlCloseTag() + "\n";
  248. return xmlStream;
  249. }
  250. void ls::std::io::XmlNode::_assignName(const ::std::string &_name)
  251. {
  252. if (_name.empty())
  253. {
  254. throw ls::std::core::IllegalArgumentException{};
  255. }
  256. this->name = _name;
  257. }
  258. void ls::std::io::XmlNode::_assignValue(const ::std::string &_value)
  259. {
  260. if (_value.empty())
  261. {
  262. throw ls::std::core::IllegalArgumentException{};
  263. }
  264. this->value = _value;
  265. }
  266. void ls::std::io::XmlNode::_checkIfAttributeReferenceIsValid(const ::std::shared_ptr<ls::std::io::XmlAttribute> &_attribute)
  267. {
  268. if (_attribute == nullptr)
  269. {
  270. throw ls::std::core::IllegalArgumentException{};
  271. }
  272. }
  273. void ls::std::io::XmlNode::_checkIfNameIsNotEmpty(const ::std::string &_name)
  274. {
  275. if (_name.empty())
  276. {
  277. throw ls::std::core::IllegalArgumentException{};
  278. }
  279. }
  280. void ls::std::io::XmlNode::_checkIfNodeReferenceIsValid(const ::std::shared_ptr<ls::std::io::XmlNode> &_child)
  281. {
  282. if (_child == nullptr)
  283. {
  284. throw ls::std::core::IllegalArgumentException{};
  285. }
  286. }
  287. std::string ls::std::io::XmlNode::_getTab(uint8_t _tabSize)
  288. {
  289. ::std::string tab{};
  290. for (uint8_t index = 0; index < _tabSize; index++)
  291. {
  292. tab += " ";
  293. }
  294. return tab;
  295. }
  296. bool ls::std::io::XmlNode::_hasAttribute(const ::std::string &_name)
  297. {
  298. bool exists{};
  299. if (_name.empty())
  300. {
  301. throw ls::std::core::IllegalArgumentException{};
  302. }
  303. else
  304. {
  305. for (const auto &attribute : this->attributes)
  306. {
  307. if (attribute->getName() == _name)
  308. {
  309. exists = true;
  310. break;
  311. }
  312. }
  313. }
  314. return exists;
  315. }
  316. bool ls::std::io::XmlNode::_hasChild(const ::std::shared_ptr<ls::std::io::XmlNode> &_child)
  317. {
  318. _checkIfNodeReferenceIsValid(_child);
  319. return ::std::find(this->children.begin(), this->children.end(), _child) != this->children.end();
  320. }
  321. bool ls::std::io::XmlNode::_hasChild(const ::std::string &_name)
  322. {
  323. bool exists{};
  324. if (_name.empty())
  325. {
  326. throw ls::std::core::IllegalArgumentException{};
  327. }
  328. else
  329. {
  330. for (const auto &attribute : this->children)
  331. {
  332. if (attribute->getName() == _name)
  333. {
  334. exists = true;
  335. break;
  336. }
  337. }
  338. }
  339. return exists;
  340. }
  341. std::string ls::std::io::XmlNode::_toXmlAttributes()
  342. {
  343. ::std::string stream{};
  344. for (const auto &_attribute : this->attributes)
  345. {
  346. stream += " " + _attribute->toXml();
  347. }
  348. return stream;
  349. }
  350. std::string ls::std::io::XmlNode::_toXmlChildren(uint8_t _tabSize)
  351. {
  352. ::std::string stream{};
  353. if (this->value.empty())
  354. {
  355. for (const auto &_child : this->children)
  356. {
  357. stream += _child->_toXml_(_tabSize);
  358. }
  359. }
  360. return stream;
  361. }
  362. std::string ls::std::io::XmlNode::_toXmlCloseTag()
  363. {
  364. ::std::string stream{};
  365. if (!this->children.empty() || !this->value.empty())
  366. {
  367. stream = "</" + this->name + ">";
  368. }
  369. return stream;
  370. }
  371. std::string ls::std::io::XmlNode::_toXmlOpenTag()
  372. {
  373. return "<" + this->name;
  374. }
  375. std::string ls::std::io::XmlNode::_toXmlOpenTagClose()
  376. {
  377. ::std::string stream{};
  378. if (this->children.empty() && this->value.empty())
  379. {
  380. stream = " />";
  381. }
  382. else
  383. {
  384. stream = ">";
  385. }
  386. return stream;
  387. }
  388. std::string ls::std::io::XmlNode::_toXmlValue()
  389. {
  390. return this->value.empty() ? "\n" : this->value;
  391. }