SimXMLDocument.cpp 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  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
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell 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
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "tinyxml/tinyxml.h"
  23. //-----------------------------------------------------------------------------
  24. // Console implementation of STL map.
  25. //-----------------------------------------------------------------------------
  26. #include "core/frameAllocator.h"
  27. #include "console/simBase.h"
  28. #include "console/consoleInternal.h"
  29. #include "console/SimXMLDocument.h"
  30. #include "console/engineAPI.h"
  31. IMPLEMENT_CONOBJECT(SimXMLDocument);
  32. ConsoleDocClass( SimXMLDocument,
  33. "@brief File I/O object used for creating, reading, and writing XML documents.\n\n"
  34. "A SimXMLDocument is a container of various XML nodes. The Document level may contain "
  35. "a header (sometimes called a declaration), comments and child Elements. Elements may "
  36. "contain attributes, data (or text) and child Elements.\n\n"
  37. "You build new Elements using addNewElement(). This makes the new Element the current "
  38. "one you're working with. You then use setAttribute() to add attributes to the Element. "
  39. "You use addData() or addText() to write to the text area of an Element."
  40. "@tsexample\n"
  41. "// Thanks to Rex Hiebert for this example\n"
  42. "// Given the following XML\n"
  43. "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>\n"
  44. "<DataTables>\n"
  45. " <table tableName=\"2DShapes\">\n"
  46. " <rec id=\"1\">Triangle</rec>\n"
  47. " <rec id=\"2\">Square</rec>\n"
  48. " <rec id=\"3\">Circle</rec>\n"
  49. " </table>\n"
  50. " <table tableName=\"3DShapes\">\n"
  51. " <rec id=\"1\">Pyramid</rec>\n"
  52. " <rec id=\"2\">Cube</rec>\n"
  53. " <rec id=\"3\">Sphere</rec>\n"
  54. " </table>\n"
  55. "</DataTables>\n\n"
  56. "// Using SimXMLDocument by itself\n"
  57. "function readXmlExample(%filename)\n"
  58. "{\n"
  59. " %xml = new SimXMLDocument() {};\n"
  60. " %xml.loadFile(%filename);\n\n"
  61. " %xml.pushChildElement(\"DataTables\");\n"
  62. " %xml.pushFirstChildElement(\"table\");\n"
  63. " while(true)\n"
  64. " {\n"
  65. " echo(\"TABLE:\" SPC %xml.attribute(\"tableName\"));\n"
  66. " %xml.pushFirstChildElement(\"rec\");\n"
  67. " while (true)\n"
  68. " {\n"
  69. " %id = %xml.attribute(\"id\");\n"
  70. " %desc = %xml.getData();\n"
  71. " echo(\" Shape\" SPC %id SPC %desc);\n"
  72. " if (!%xml.nextSiblingElement(\"rec\")) break;\n"
  73. " }\n"
  74. " %xml.popElement();\n"
  75. " if (!%xml.nextSiblingElement(\"table\")) break;\n"
  76. " }\n"
  77. "}\n\n"
  78. "// Thanks to Scott Peal for this example\n"
  79. "// Using FileObject in conjunction with SimXMLDocument\n"
  80. "// This example uses an XML file with a format of:\n"
  81. "// <Models>\n"
  82. "// <Model category=\"\" name=\"\" path=\"\" />\n"
  83. "// </Models>\n"
  84. "function getModelsInCatagory()\n"
  85. "{\n"
  86. " %file = \"./Catalog.xml\";\n"
  87. " %fo = new FileObject();\n"
  88. " %text = \"\";\n\n"
  89. " if(%fo.openForRead(%file))\n"
  90. " {\n"
  91. " while(!%fo.isEOF())\n"
  92. " {\n"
  93. " %text = %text @ %fo.readLine();\n"
  94. " if (!%fo.isEOF()) %text = %text @ \"\\n\";\n"
  95. " }\n"
  96. " }\n"
  97. " else\n"
  98. " {\n"
  99. " echo(\"Unable to locate the file: \" @ %file);\n"
  100. " }\n\n"
  101. " %fo.delete();\n\n"
  102. " %xml = new SimXMLDocument() {};\n"
  103. " %xml.parse(%text);\n"
  104. " // \"Get\" inside of the root element, \"Models\".\n"
  105. " %xml.pushChildElement(0);\n\n"
  106. " // \"Get\" into the first child element\n"
  107. " if (%xml.pushFirstChildElement(\"Model\"))\n"
  108. " {\n"
  109. " while (true)\n"
  110. " {\n"
  111. " // \n"
  112. " // Here, i read the element's attributes.\n"
  113. " // You might want to save these values in an array or call the %xml.getElementValue()\n"
  114. " // if you have a different XML structure.\n\n"
  115. " %catagory = %xml.attribute(\"catagory\");\n"
  116. " %name = %xml.attribute(\"name\");\n"
  117. " %path = %xml.attribute(\"path\");\n\n"
  118. " // now, read the next \"Model\"\n"
  119. " if (!%xml.nextSiblingElement(\"Model\")) break;\n"
  120. " }\n"
  121. " }\n"
  122. "}\n"
  123. "@endtsexample\n\n"
  124. "@note SimXMLDocument is a wrapper around TinyXml, a standard XML library. If you're familiar "
  125. "with its concepts, you'll find they also apply here.\n\n"
  126. "@see FileObject\n\n"
  127. "@ingroup FileSystem\n"
  128. );
  129. // -----------------------------------------------------------------------------
  130. // Constructor.
  131. // -----------------------------------------------------------------------------
  132. SimXMLDocument::SimXMLDocument():
  133. m_qDocument(0),
  134. m_CurrentAttribute(0)
  135. {
  136. }
  137. // -----------------------------------------------------------------------------
  138. // Destructor.
  139. // -----------------------------------------------------------------------------
  140. SimXMLDocument::~SimXMLDocument()
  141. {
  142. }
  143. // -----------------------------------------------------------------------------
  144. // Included for completeness.
  145. // -----------------------------------------------------------------------------
  146. bool SimXMLDocument::processArguments(S32 argc, ConsoleValueRef *argv)
  147. {
  148. return argc == 0;
  149. }
  150. // -----------------------------------------------------------------------------
  151. // Script constructor.
  152. // -----------------------------------------------------------------------------
  153. bool SimXMLDocument::onAdd()
  154. {
  155. if(!Parent::onAdd())
  156. {
  157. return false;
  158. }
  159. if(!m_qDocument)
  160. {
  161. m_qDocument = new TiXmlDocument();
  162. }
  163. return true;
  164. }
  165. // -----------------------------------------------------------------------------
  166. // Script destructor.
  167. // -----------------------------------------------------------------------------
  168. void SimXMLDocument::onRemove()
  169. {
  170. Parent::onRemove();
  171. if(m_qDocument)
  172. {
  173. m_qDocument->Clear();
  174. delete(m_qDocument);
  175. }
  176. }
  177. // -----------------------------------------------------------------------------
  178. // Initialize peristent fields (datablocks).
  179. // -----------------------------------------------------------------------------
  180. void SimXMLDocument::initPersistFields()
  181. {
  182. Parent::initPersistFields();
  183. }
  184. // -----------------------------------------------------------------------------
  185. // Set this to default state at construction.
  186. // -----------------------------------------------------------------------------
  187. void SimXMLDocument::reset(void)
  188. {
  189. m_qDocument->Clear();
  190. m_paNode.clear();
  191. m_CurrentAttribute = 0;
  192. }
  193. DefineEngineMethod( SimXMLDocument, reset, void, (),,
  194. "@brief Set this document to its default state.\n\n"
  195. "Clears all Elements from the documents. Equivalent to using clear()\n\n"
  196. "@see clear()")
  197. {
  198. object->reset();
  199. }
  200. // -----------------------------------------------------------------------------
  201. // Get true if file loads successfully.
  202. // -----------------------------------------------------------------------------
  203. bool SimXMLDocument::loadFile(const char* rFileName)
  204. {
  205. reset();
  206. return m_qDocument->LoadFile(rFileName);
  207. }
  208. DefineEngineMethod( SimXMLDocument, loadFile, bool, ( const char* fileName ),,
  209. "@brief Load in given filename and prepare it for use.\n\n"
  210. "@note Clears the current document's contents.\n\n"
  211. "@param fileName Name and path of XML document\n"
  212. "@return True if the file was loaded successfully.")
  213. {
  214. return object->loadFile( fileName );
  215. }
  216. // -----------------------------------------------------------------------------
  217. // Get true if file saves successfully.
  218. // -----------------------------------------------------------------------------
  219. bool SimXMLDocument::saveFile(const char* rFileName)
  220. {
  221. return m_qDocument->SaveFile( rFileName );
  222. }
  223. // -----------------------------------------------------------------------------
  224. // Get true if file saves successfully to string.
  225. // -----------------------------------------------------------------------------
  226. bool SimXMLDocument::saveToString(String& str)
  227. {
  228. TiXmlPrinter printer;
  229. bool ret = m_qDocument->Accept( &printer );
  230. if (ret)
  231. str = printer.CStr();
  232. return ret;
  233. }
  234. DefineEngineMethod( SimXMLDocument, saveFile, bool, ( const char* fileName ),,
  235. "@brief Save document to the given file name.\n\n"
  236. "@param fileName Path and name of XML file to save to.\n"
  237. "@return True if the file was successfully saved.")
  238. {
  239. return object->saveFile( fileName );
  240. }
  241. // -----------------------------------------------------------------------------
  242. // Get true if XML text parses correctly.
  243. // -----------------------------------------------------------------------------
  244. S32 SimXMLDocument::parse(const char* rText)
  245. {
  246. reset();
  247. m_qDocument->Parse( rText );
  248. return 1;
  249. }
  250. DefineEngineMethod( SimXMLDocument, parse, void, ( const char* xmlString ),,
  251. "@brief Create a document from a XML string.\n\n"
  252. "@note Clears the current document's contents.\n\n"
  253. "@param xmlString Valid XML to parse and store as a document.")
  254. {
  255. object->parse( xmlString );
  256. }
  257. // -----------------------------------------------------------------------------
  258. // Clear contents of XML document.
  259. // -----------------------------------------------------------------------------
  260. void SimXMLDocument::clear(void)
  261. {
  262. reset();
  263. }
  264. DefineEngineMethod( SimXMLDocument, clear, void, (),,
  265. "@brief Set this document to its default state.\n\n"
  266. "Clears all Elements from the documents. Equivalent to using reset()\n\n"
  267. "@see reset()")
  268. {
  269. object->clear();
  270. }
  271. // -----------------------------------------------------------------------------
  272. // Get error description of XML document.
  273. // -----------------------------------------------------------------------------
  274. const char* SimXMLDocument::getErrorDesc(void) const
  275. {
  276. if(!m_qDocument)
  277. {
  278. return StringTable->insert("No document");
  279. }
  280. return m_qDocument->ErrorDesc();
  281. }
  282. DefineEngineMethod( SimXMLDocument, getErrorDesc, const char*, (),,
  283. "@brief Get last error description.\n\n"
  284. "@return A string of the last error message.")
  285. {
  286. return object->getErrorDesc();
  287. }
  288. // -----------------------------------------------------------------------------
  289. // Clear error description of this.
  290. // -----------------------------------------------------------------------------
  291. void SimXMLDocument::clearError(void)
  292. {
  293. m_qDocument->ClearError();
  294. }
  295. DefineEngineMethod( SimXMLDocument, clearError, void, (),,
  296. "@brief Clear the last error description.\n\n")
  297. {
  298. object->clearError();
  299. }
  300. // -----------------------------------------------------------------------------
  301. // Get true if first child element was successfully pushed onto stack.
  302. // -----------------------------------------------------------------------------
  303. bool SimXMLDocument::pushFirstChildElement(const char* rName)
  304. {
  305. // Clear the current attribute pointer
  306. m_CurrentAttribute = 0;
  307. // Push the first element found under the current element of the given name
  308. TiXmlElement* pElement;
  309. if(!m_paNode.empty())
  310. {
  311. const S32 iLastElement = m_paNode.size() - 1;
  312. TiXmlElement* pNode = m_paNode[iLastElement];
  313. if(!pNode)
  314. {
  315. return false;
  316. }
  317. pElement = pNode->FirstChildElement(rName);
  318. }
  319. else
  320. {
  321. if(!m_qDocument)
  322. {
  323. return false;
  324. }
  325. pElement = m_qDocument->FirstChildElement(rName);
  326. }
  327. if(!pElement)
  328. {
  329. return false;
  330. }
  331. m_paNode.push_back(pElement);
  332. return true;
  333. }
  334. DefineEngineMethod( SimXMLDocument, pushFirstChildElement, bool, ( const char* name ),,
  335. "@brief Push the first child Element with the given name onto the stack, making it the current Element.\n\n"
  336. "@param name String containing name of the child Element.\n"
  337. "@return True if the Element was found and made the current one.\n"
  338. "@tsexample\n"
  339. "// Using the following test.xml file as an example:\n"
  340. "// <?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>\n"
  341. "// <NewElement>Some text</NewElement>\n\n"
  342. "// Load in the file\n"
  343. "%x = new SimXMLDocument();\n"
  344. "%x.loadFile(\"test.xml\");\n\n"
  345. "// Make the first Element the current one\n"
  346. "%x.pushFirstChildElement(\"NewElement\");\n\n"
  347. "// Store the current Element's text ('Some text' in this example)\n"
  348. "// into 'result'\n"
  349. "%result = %x.getText();\n"
  350. "echo( %result );\n"
  351. "@endtsexample\n\n")
  352. {
  353. return object->pushFirstChildElement( name );
  354. }
  355. // -----------------------------------------------------------------------------
  356. // Get true if first child element was successfully pushed onto stack.
  357. // -----------------------------------------------------------------------------
  358. bool SimXMLDocument::pushChildElement(S32 index)
  359. {
  360. // Clear the current attribute pointer
  361. m_CurrentAttribute = 0;
  362. // Push the first element found under the current element of the given name
  363. TiXmlElement* pElement;
  364. if(!m_paNode.empty())
  365. {
  366. const S32 iLastElement = m_paNode.size() - 1;
  367. TiXmlElement* pNode = m_paNode[iLastElement];
  368. if(!pNode)
  369. {
  370. return false;
  371. }
  372. pElement = pNode->FirstChildElement();
  373. for( S32 i = 0; i < index; i++ )
  374. {
  375. if( !pElement )
  376. return false;
  377. pElement = pElement->NextSiblingElement();
  378. }
  379. }
  380. else
  381. {
  382. if(!m_qDocument)
  383. {
  384. return false;
  385. }
  386. pElement = m_qDocument->FirstChildElement();
  387. for( S32 i = 0; i < index; i++ )
  388. {
  389. if( !pElement )
  390. return false;
  391. pElement = pElement->NextSiblingElement();
  392. }
  393. }
  394. if(!pElement)
  395. {
  396. return false;
  397. }
  398. m_paNode.push_back(pElement);
  399. return true;
  400. }
  401. DefineEngineMethod( SimXMLDocument, pushChildElement, bool, ( S32 index ),,
  402. "@brief Push the child Element at the given index onto the stack, making it the current one.\n\n"
  403. "@param index Numerical index of Element being pushed."
  404. "@return True if the Element was found and made the current one.\n")
  405. {
  406. return object->pushChildElement( index );
  407. }
  408. // -----------------------------------------------------------------------------
  409. // Convert top stack element into its next sibling element.
  410. // -----------------------------------------------------------------------------
  411. bool SimXMLDocument::nextSiblingElement(const char* rName)
  412. {
  413. // Clear the current attribute pointer
  414. m_CurrentAttribute = 0;
  415. // Attempt to find the next sibling element
  416. if(m_paNode.empty())
  417. {
  418. return false;
  419. }
  420. const S32 iLastElement = m_paNode.size() - 1;
  421. TiXmlElement*& pElement = m_paNode[iLastElement];
  422. if(!pElement)
  423. {
  424. return false;
  425. }
  426. pElement = pElement->NextSiblingElement(rName);
  427. if(!pElement)
  428. {
  429. return false;
  430. }
  431. return true;
  432. }
  433. DefineEngineMethod( SimXMLDocument, nextSiblingElement, bool, ( const char* name ),,
  434. "@brief Put the next sibling Element with the given name on the stack, making it the current one.\n\n"
  435. "@param name String containing name of the next sibling."
  436. "@return True if the Element was found and made the current one.\n")
  437. {
  438. return object->nextSiblingElement( name );
  439. }
  440. // -----------------------------------------------------------------------------
  441. // Get element value if it exists. Used to extract a text node from the element.
  442. // for example.
  443. // -----------------------------------------------------------------------------
  444. const char* SimXMLDocument::elementValue()
  445. {
  446. if(m_paNode.empty())
  447. {
  448. return StringTable->insert("");
  449. }
  450. const S32 iLastElement = m_paNode.size() - 1;
  451. TiXmlElement* pNode = m_paNode[iLastElement];
  452. if(!pNode)
  453. {
  454. return StringTable->insert("");
  455. }
  456. return pNode->Value();
  457. }
  458. DefineEngineMethod( SimXMLDocument, elementValue, const char*, (),,
  459. "@brief Get the Element's value if it exists.\n\n"
  460. "Usually returns the text from the Element.\n"
  461. "@return The value from the Element, or an empty string if none is found.")
  462. {
  463. return object->elementValue();
  464. }
  465. // -----------------------------------------------------------------------------
  466. // Pop last element off of stack.
  467. // -----------------------------------------------------------------------------
  468. void SimXMLDocument::popElement(void)
  469. {
  470. m_paNode.pop_back();
  471. }
  472. DefineEngineMethod( SimXMLDocument, popElement, void, (),,
  473. "@brief Pop the last Element off the stack.\n\n")
  474. {
  475. object->popElement();
  476. }
  477. // -----------------------------------------------------------------------------
  478. // Get attribute value if it exists.
  479. // -----------------------------------------------------------------------------
  480. const char* SimXMLDocument::attribute(const char* rAttribute)
  481. {
  482. if(m_paNode.empty())
  483. {
  484. return StringTable->insert("");
  485. }
  486. const S32 iLastElement = m_paNode.size() - 1;
  487. TiXmlElement* pNode = m_paNode[iLastElement];
  488. if(!pNode)
  489. {
  490. return StringTable->insert("");
  491. }
  492. if(!pNode->Attribute(rAttribute))
  493. {
  494. return StringTable->insert("");
  495. }
  496. return pNode->Attribute(rAttribute);
  497. }
  498. DefineEngineMethod( SimXMLDocument, attribute, const char*, ( const char* attributeName ),,
  499. "@brief Get a string attribute from the current Element on the stack.\n\n"
  500. "@param attributeName Name of attribute to retrieve.\n"
  501. "@return The attribute string if found. Otherwise returns an empty string.\n")
  502. {
  503. return object->attribute( attributeName );
  504. }
  505. // These two methods don't make a lot of sense the way TS works. Leaving them in for backwards-compatibility.
  506. ConsoleMethod( SimXMLDocument, attributeF32, F32, 3, 3, "(string attributeName)"
  507. "@brief Get float attribute from the current Element on the stack.\n\n"
  508. "@param attributeName Name of attribute to retrieve.\n"
  509. "@return The value of the given attribute in the form of a float.\n"
  510. "@deprecated Use attribute().")
  511. {
  512. return dAtof( object->attribute( argv[2] ) );
  513. }
  514. ConsoleMethod(SimXMLDocument, attributeS32, S32, 3, 3, "(string attributeName)"
  515. "@brief Get int attribute from the current Element on the stack.\n\n"
  516. "@param attributeName Name of attribute to retrieve.\n"
  517. "@return The value of the given attribute in the form of an integer.\n"
  518. "@deprecated Use attribute().")
  519. {
  520. return dAtoi( object->attribute( argv[2] ) );
  521. }
  522. // -----------------------------------------------------------------------------
  523. // Get true if given attribute exists.
  524. // -----------------------------------------------------------------------------
  525. bool SimXMLDocument::attributeExists(const char* rAttribute)
  526. {
  527. if(m_paNode.empty())
  528. {
  529. return false;
  530. }
  531. const S32 iLastElement = m_paNode.size() - 1;
  532. TiXmlElement* pNode = m_paNode[iLastElement];
  533. if(!pNode)
  534. {
  535. return false;
  536. }
  537. if(!pNode->Attribute(rAttribute))
  538. {
  539. return false;
  540. }
  541. return true;
  542. }
  543. DefineEngineMethod( SimXMLDocument, attributeExists, bool, ( const char* attributeName ),,
  544. "@brief Tests if the requested attribute exists.\n\n"
  545. "@param attributeName Name of attribute being queried for.\n\n"
  546. "@return True if the attribute exists.")
  547. {
  548. return object->attributeExists( attributeName );
  549. }
  550. // -----------------------------------------------------------------------------
  551. // Obtain the name of the current element's first attribute
  552. // -----------------------------------------------------------------------------
  553. const char* SimXMLDocument::firstAttribute()
  554. {
  555. // Get the current element
  556. if(m_paNode.empty())
  557. {
  558. return StringTable->insert("");
  559. }
  560. const S32 iLastElement = m_paNode.size() - 1;
  561. TiXmlElement* pNode = m_paNode[iLastElement];
  562. if(!pNode)
  563. {
  564. return StringTable->insert("");
  565. }
  566. // Gets its first attribute, if any
  567. m_CurrentAttribute = pNode->FirstAttribute();
  568. if(!m_CurrentAttribute)
  569. {
  570. return StringTable->insert("");
  571. }
  572. return m_CurrentAttribute->Name();
  573. }
  574. DefineEngineMethod( SimXMLDocument, firstAttribute, const char*, (),,
  575. "@brief Obtain the name of the current Element's first attribute.\n\n"
  576. "@return String containing the first attribute's name, or an empty string if none is found.\n\n"
  577. "@see nextAttribute()\n"
  578. "@see lastAttribute()\n"
  579. "@see prevAttribute()")
  580. {
  581. return object->firstAttribute();
  582. }
  583. // -----------------------------------------------------------------------------
  584. // Obtain the name of the current element's last attribute
  585. // -----------------------------------------------------------------------------
  586. const char* SimXMLDocument::lastAttribute()
  587. {
  588. // Get the current element
  589. if(m_paNode.empty())
  590. {
  591. return StringTable->insert("");
  592. }
  593. const S32 iLastElement = m_paNode.size() - 1;
  594. TiXmlElement* pNode = m_paNode[iLastElement];
  595. if(!pNode)
  596. {
  597. return StringTable->insert("");
  598. }
  599. // Gets its last attribute, if any
  600. m_CurrentAttribute = pNode->LastAttribute();
  601. if(!m_CurrentAttribute)
  602. {
  603. return StringTable->insert("");
  604. }
  605. return m_CurrentAttribute->Name();
  606. }
  607. DefineEngineMethod( SimXMLDocument, lastAttribute, const char*, (),,
  608. "@brief Obtain the name of the current Element's last attribute.\n\n"
  609. "@return String containing the last attribute's name, or an empty string if none is found.\n\n"
  610. "@see prevAttribute()\n"
  611. "@see firstAttribute()\n"
  612. "@see lastAttribute()\n")
  613. {
  614. return object->lastAttribute();
  615. }
  616. // -----------------------------------------------------------------------------
  617. // Get the name of the next attribute for the current element after a call
  618. // to firstAttribute().
  619. // -----------------------------------------------------------------------------
  620. const char* SimXMLDocument::nextAttribute()
  621. {
  622. if(!m_CurrentAttribute)
  623. {
  624. return StringTable->insert("");
  625. }
  626. // Gets its next attribute, if any
  627. m_CurrentAttribute = m_CurrentAttribute->Next();
  628. if(!m_CurrentAttribute)
  629. {
  630. return StringTable->insert("");
  631. }
  632. return m_CurrentAttribute->Name();
  633. }
  634. DefineEngineMethod( SimXMLDocument, nextAttribute, const char*, (),,
  635. "@brief Get the name of the next attribute for the current Element after a call to firstAttribute().\n\n"
  636. "@return String containing the next attribute's name, or an empty string if none is found."
  637. "@see firstAttribute()\n"
  638. "@see lastAttribute()\n"
  639. "@see prevAttribute()\n")
  640. {
  641. return object->nextAttribute();
  642. }
  643. // -----------------------------------------------------------------------------
  644. // Get the name of the previous attribute for the current element after a call
  645. // to lastAttribute().
  646. // -----------------------------------------------------------------------------
  647. const char* SimXMLDocument::prevAttribute()
  648. {
  649. if(!m_CurrentAttribute)
  650. {
  651. return StringTable->insert("");
  652. }
  653. // Gets its next attribute, if any
  654. m_CurrentAttribute = m_CurrentAttribute->Previous();
  655. if(!m_CurrentAttribute)
  656. {
  657. return StringTable->insert("");
  658. }
  659. return m_CurrentAttribute->Name();
  660. }
  661. DefineEngineMethod( SimXMLDocument, prevAttribute, const char*, (),,
  662. "@brief Get the name of the previous attribute for the current Element after a call to lastAttribute().\n\n"
  663. "@return String containing the previous attribute's name, or an empty string if none is found."
  664. "@see lastAttribute()\n"
  665. "@see firstAttribute()\n"
  666. "@see nextAttribute()\n")
  667. {
  668. return object->prevAttribute();
  669. }
  670. // -----------------------------------------------------------------------------
  671. // Set attribute of top stack element to given value.
  672. // -----------------------------------------------------------------------------
  673. void SimXMLDocument::setAttribute(const char* rAttribute, const char* rVal)
  674. {
  675. if(m_paNode.empty())
  676. {
  677. return;
  678. }
  679. const S32 iLastElement = m_paNode.size() - 1;
  680. TiXmlElement* pElement = m_paNode[iLastElement];
  681. if(!pElement)
  682. {
  683. return;
  684. }
  685. pElement->SetAttribute(rAttribute, rVal);
  686. }
  687. DefineEngineMethod( SimXMLDocument, setAttribute, void, ( const char* attributeName, const char* value ),,
  688. "@brief Set the attribute of the current Element on the stack to the given value.\n\n"
  689. "@param attributeName Name of attribute being changed\n"
  690. "@param value New value to assign to the attribute\n")
  691. {
  692. object->setAttribute( attributeName, value );
  693. }
  694. // -----------------------------------------------------------------------------
  695. // Set attribute of top stack element to given value.
  696. // -----------------------------------------------------------------------------
  697. void SimXMLDocument::setObjectAttributes(const char* objectID)
  698. {
  699. if( !objectID || !objectID[0] )
  700. return;
  701. if(m_paNode.empty())
  702. return;
  703. SimObject *pObject = Sim::findObject( objectID );
  704. if( pObject == NULL )
  705. return;
  706. const S32 iLastElement = m_paNode.size() - 1;
  707. TiXmlElement* pElement = m_paNode[iLastElement];
  708. if(!pElement)
  709. return;
  710. char textbuf[1024];
  711. TiXmlElement field( "Field" );
  712. TiXmlElement group( "FieldGroup" );
  713. pElement->SetAttribute( "Name", pObject->getName() );
  714. // Iterate over our filed list and add them to the XML document...
  715. AbstractClassRep::FieldList fieldList = pObject->getFieldList();
  716. AbstractClassRep::FieldList::iterator itr;
  717. for(itr = fieldList.begin(); itr != fieldList.end(); itr++)
  718. {
  719. if( itr->type == AbstractClassRep::DeprecatedFieldType ||
  720. itr->type == AbstractClassRep::StartGroupFieldType ||
  721. itr->type == AbstractClassRep::EndGroupFieldType) continue;
  722. // Not an Array
  723. if(itr->elementCount == 1)
  724. {
  725. // get the value of the field as a string.
  726. ConsoleBaseType *cbt = ConsoleBaseType::getType(itr->type);
  727. const char *val = Con::getData(itr->type, (void *) (((const char *)pObject) + itr->offset), 0, itr->table, itr->flag);
  728. // Make a copy for the field check.
  729. if (!val)
  730. continue;
  731. FrameTemp<char> valCopy( dStrlen( val ) + 1 );
  732. dStrcpy( (char *)valCopy, val );
  733. if (!pObject->writeField(itr->pFieldname, valCopy))
  734. continue;
  735. val = valCopy;
  736. expandEscape(textbuf, val);
  737. if( !pObject->writeField( itr->pFieldname, textbuf ) )
  738. continue;
  739. field.SetValue( "Property" );
  740. field.SetAttribute( "name", itr->pFieldname );
  741. if( cbt != NULL )
  742. field.SetAttribute( "type", cbt->getTypeName() );
  743. else
  744. field.SetAttribute( "type", "TypeString" );
  745. field.SetAttribute( "data", textbuf );
  746. pElement->InsertEndChild( field );
  747. continue;
  748. }
  749. }
  750. //// IS An Array
  751. //for(U32 j = 0; S32(j) < f->elementCount; j++)
  752. //{
  753. // // If the start of a group create an element for the group and
  754. // // the our chache to it
  755. // const char *val = Con::getData(itr->type, (void *) (((const char *)pObject) + itr->offset), j, itr->table, itr->flag);
  756. // // Make a copy for the field check.
  757. // if (!val)
  758. // continue;
  759. // FrameTemp<char> valCopy( dStrlen( val ) + 1 );
  760. // dStrcpy( (char *)valCopy, val );
  761. // if (!pObject->writeField(itr->pFieldname, valCopy))
  762. // continue;
  763. // val = valCopy;
  764. // // get the value of the field as a string.
  765. // ConsoleBaseType *cbt = ConsoleBaseType::getType(itr->type);
  766. // const char * dstr = Con::getData(itr->type, (void *)(((const char *)pObject) + itr->offset), 0, itr->table, itr->flag);
  767. // if(!dstr)
  768. // dstr = "";
  769. // expandEscape(textbuf, dstr);
  770. // if( !pObject->writeField( itr->pFieldname, dstr ) )
  771. // continue;
  772. // field.SetValue( "Property" );
  773. // field.SetAttribute( "name", itr->pFieldname );
  774. // if( cbt != NULL )
  775. // field.SetAttribute( "type", cbt->getTypeName() );
  776. // else
  777. // field.SetAttribute( "type", "TypeString" );
  778. // field.SetAttribute( "data", textbuf );
  779. // pElement->InsertEndChild( field );
  780. //}
  781. }
  782. DefineEngineMethod( SimXMLDocument, setObjectAttributes, void, ( const char* objectID ),,
  783. "@brief Add the given SimObject's fields as attributes of the current Element on the stack.\n\n"
  784. "@param objectID ID of SimObject being copied.")
  785. {
  786. object->setObjectAttributes( objectID );
  787. }
  788. // -----------------------------------------------------------------------------
  789. // Create a new element and set to child of current stack element.
  790. // New element is placed on top of element stack.
  791. // -----------------------------------------------------------------------------
  792. void SimXMLDocument::pushNewElement(const char* rName)
  793. {
  794. TiXmlElement cElement( rName );
  795. TiXmlElement* pStackTop = 0;
  796. if(m_paNode.empty())
  797. {
  798. pStackTop = dynamic_cast<TiXmlElement*>
  799. (m_qDocument->InsertEndChild( cElement ) );
  800. }
  801. else
  802. {
  803. const S32 iFinalElement = m_paNode.size() - 1;
  804. TiXmlElement* pNode = m_paNode[iFinalElement];
  805. if(!pNode)
  806. {
  807. return;
  808. }
  809. pStackTop = dynamic_cast<TiXmlElement*>
  810. (pNode->InsertEndChild( cElement ));
  811. }
  812. if(!pStackTop)
  813. {
  814. return;
  815. }
  816. m_paNode.push_back(pStackTop);
  817. }
  818. DefineEngineMethod( SimXMLDocument, pushNewElement, void, ( const char* name ),,
  819. "@brief Create a new element with the given name as child of current Element "
  820. "and push it onto the Element stack making it the current one.\n\n"
  821. "@note This differs from addNewElement() in that it adds the new Element as a "
  822. "child of the current Element (or a child of the document if no Element exists).\n\n"
  823. "@param name XML tag for the new Element.\n"
  824. "@see addNewElement()")
  825. {
  826. object->pushNewElement( name );
  827. }
  828. // -----------------------------------------------------------------------------
  829. // Create a new element and set to child of current stack element.
  830. // New element is placed on top of element stack.
  831. // -----------------------------------------------------------------------------
  832. void SimXMLDocument::addNewElement(const char* rName)
  833. {
  834. TiXmlElement cElement( rName );
  835. TiXmlElement* pStackTop = 0;
  836. if(m_paNode.empty())
  837. {
  838. pStackTop = dynamic_cast<TiXmlElement*>
  839. (m_qDocument->InsertEndChild( cElement ));
  840. if(!pStackTop)
  841. {
  842. return;
  843. }
  844. m_paNode.push_back(pStackTop);
  845. return;
  846. }
  847. const S32 iParentElement = m_paNode.size() - 2;
  848. if(iParentElement < 0)
  849. {
  850. pStackTop = dynamic_cast<TiXmlElement*>
  851. (m_qDocument->InsertEndChild( cElement ));
  852. if(!pStackTop)
  853. {
  854. return;
  855. }
  856. m_paNode.push_back(pStackTop);
  857. return;
  858. }
  859. else
  860. {
  861. TiXmlElement* pNode = m_paNode[iParentElement];
  862. if(!pNode)
  863. {
  864. return;
  865. }
  866. pStackTop = dynamic_cast<TiXmlElement*>
  867. (pNode->InsertEndChild( cElement ));
  868. if(!pStackTop)
  869. {
  870. return;
  871. }
  872. // Overwrite top stack position.
  873. const S32 iFinalElement = m_paNode.size() - 1;
  874. m_paNode[iFinalElement] = pStackTop;
  875. //pNode = pStackTop;
  876. }
  877. }
  878. DefineEngineMethod( SimXMLDocument, addNewElement, void, ( const char* name ),,
  879. "@brief Create a new element with the given name as child of current Element's "
  880. "parent and push it onto the Element stack making it the current one.\n\n"
  881. "@note This differs from pushNewElement() in that it adds the new Element to the "
  882. "current Element's parent (or document if there is no parent Element). This makes "
  883. "the new Element a sibling of the current one.\n\n"
  884. "@param name XML tag for the new Element.\n"
  885. "@see pushNewElement()")
  886. {
  887. object->addNewElement( name );
  888. }
  889. // -----------------------------------------------------------------------------
  890. // Write XML document declaration.
  891. // -----------------------------------------------------------------------------
  892. void SimXMLDocument::addHeader(void)
  893. {
  894. TiXmlDeclaration cDeclaration("1.0", "utf-8", "yes");
  895. m_qDocument->InsertEndChild(cDeclaration);
  896. }
  897. DefineEngineMethod( SimXMLDocument, addHeader, void, (),,
  898. "@brief Add a XML header to a document.\n\n"
  899. "Sometimes called a declaration, you typically add a standard header to "
  900. "the document before adding any elements. SimXMLDocument always produces "
  901. "the following header:\n\n"
  902. "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>\n\n"
  903. "@tsexample\n"
  904. "// Create a new XML document with just a header and single element.\n"
  905. "%x = new SimXMLDocument();\n"
  906. "%x.addHeader();\n"
  907. "%x.addNewElement(\"NewElement\");\n"
  908. "%x.saveFile(\"test.xml\");\n\n"
  909. "// Produces the following file:\n"
  910. "// <?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>\n"
  911. "// <NewElement />\n"
  912. "@endtsexample\n\n")
  913. {
  914. object->addHeader();
  915. }
  916. void SimXMLDocument::addComment(const char* comment)
  917. {
  918. TiXmlComment cComment;
  919. cComment.SetValue(comment);
  920. m_qDocument->InsertEndChild(cComment);
  921. }
  922. DefineEngineMethod(SimXMLDocument, addComment, void, ( const char* comment ),,
  923. "@brief Add the given comment as a child of the document.\n\n"
  924. "@param comment String containing the comment."
  925. "@tsexample\n"
  926. "// Create a new XML document with a header, a comment and single element.\n"
  927. "%x = new SimXMLDocument();\n"
  928. "%x.addHeader();\n"
  929. "%x.addComment(\"This is a test comment\");\n"
  930. "%x.addNewElement(\"NewElement\");\n"
  931. "%x.saveFile(\"test.xml\");\n\n"
  932. "// Produces the following file:\n"
  933. "// <?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>\n"
  934. "// <!--This is a test comment-->\n"
  935. "// <NewElement />\n"
  936. "@endtsexample\n\n"
  937. "@see readComment()")
  938. {
  939. object->addComment( comment );
  940. }
  941. const char* SimXMLDocument::readComment( S32 index )
  942. {
  943. // Clear the current attribute pointer
  944. m_CurrentAttribute = 0;
  945. // Push the first element found under the current element of the given name
  946. if(!m_paNode.empty())
  947. {
  948. const S32 iLastElement = m_paNode.size() - 1;
  949. TiXmlElement* pNode = m_paNode[iLastElement];
  950. if(!pNode)
  951. {
  952. return "";
  953. }
  954. TiXmlNode* node = pNode->FirstChild();
  955. for( S32 i = 0; i < index; i++ )
  956. {
  957. if( !node )
  958. return "";
  959. node = node->NextSiblingElement();
  960. }
  961. if( node )
  962. {
  963. TiXmlComment* comment = node->ToComment();
  964. if( comment )
  965. return comment->Value();
  966. }
  967. }
  968. else
  969. {
  970. if(!m_qDocument)
  971. {
  972. return "";
  973. }
  974. TiXmlNode* node = m_qDocument->FirstChild();
  975. for( S32 i = 0; i < index; i++ )
  976. {
  977. if( !node )
  978. return "";
  979. node = node->NextSibling();
  980. }
  981. if( node )
  982. {
  983. TiXmlComment* comment = node->ToComment();
  984. if( comment )
  985. return comment->Value();
  986. }
  987. }
  988. return "";
  989. }
  990. DefineEngineMethod( SimXMLDocument, readComment, const char*, ( S32 index ),,
  991. "Gives the comment at the specified index, if any.\n\n"
  992. "Unlike addComment() that only works at the document level, readComment() may read "
  993. "comments from the document or any child Element. The current Element (or document "
  994. "if no Elements have been pushed to the stack) is the parent for any comments, and the "
  995. "provided index is the number of comments in to read back."
  996. "@param index Comment index number to query from the current Element stack\n\n"
  997. "@return String containing the comment, or an empty string if no comment is found.\n\n"
  998. "@see addComment()")
  999. {
  1000. return object->readComment( index );
  1001. }
  1002. void SimXMLDocument::addText(const char* text)
  1003. {
  1004. if(m_paNode.empty())
  1005. return;
  1006. const S32 iFinalElement = m_paNode.size() - 1;
  1007. TiXmlElement* pNode = m_paNode[iFinalElement];
  1008. if(!pNode)
  1009. return;
  1010. TiXmlText cText(text);
  1011. pNode->InsertEndChild( cText );
  1012. }
  1013. DefineEngineMethod( SimXMLDocument, addText, void, ( const char* text ),,
  1014. "@brief Add the given text as a child of current Element.\n\n"
  1015. "Use getText() to retrieve any text from the current Element and removeText() "
  1016. "to clear any text.\n\n"
  1017. "addText() and addData() may be used interchangeably."
  1018. "@param text String containing the text.\n\n"
  1019. "@tsexample\n"
  1020. "// Create a new XML document with a header and single element\n"
  1021. "// with some added text.\n"
  1022. "%x = new SimXMLDocument();\n"
  1023. "%x.addHeader();\n"
  1024. "%x.addNewElement(\"NewElement\");\n"
  1025. "%x.addText(\"Some text\");\n"
  1026. "%x.saveFile(\"test.xml\");\n\n"
  1027. "// Produces the following file:\n"
  1028. "// <?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>\n"
  1029. "// <NewElement>Some text</NewElement>\n"
  1030. "@endtsexample\n\n"
  1031. "@see getText()\n"
  1032. "@see removeText()\n"
  1033. "@see addData()\n"
  1034. "@see getData()")
  1035. {
  1036. object->addText( text );
  1037. }
  1038. const char* SimXMLDocument::getText()
  1039. {
  1040. if(m_paNode.empty())
  1041. return "";
  1042. const S32 iFinalElement = m_paNode.size() - 1;
  1043. TiXmlNode* pNode = m_paNode[iFinalElement];
  1044. if(!pNode)
  1045. return "";
  1046. if(!pNode->FirstChild())
  1047. return "";
  1048. TiXmlText* text = pNode->FirstChild()->ToText();
  1049. if( !text )
  1050. return "";
  1051. return text->Value();
  1052. }
  1053. DefineEngineMethod( SimXMLDocument, getText, const char*, (),,
  1054. "@brief Gets the text from the current Element.\n\n"
  1055. "Use addText() to add text to the current Element and removeText() "
  1056. "to clear any text.\n\n"
  1057. "getText() and getData() may be used interchangeably."
  1058. "@return String containing the text in the current Element."
  1059. "@tsexample\n"
  1060. "// Using the following test.xml file as an example:\n"
  1061. "// <?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>\n"
  1062. "// <NewElement>Some text</NewElement>\n\n"
  1063. "// Load in the file\n"
  1064. "%x = new SimXMLDocument();\n"
  1065. "%x.loadFile(\"test.xml\");\n\n"
  1066. "// Make the first Element the current one\n"
  1067. "%x.pushFirstChildElement(\"NewElement\");\n\n"
  1068. "// Store the current Element's text ('Some text' in this example)\n"
  1069. "// into 'result'\n"
  1070. "%result = %x.getText();\n"
  1071. "echo( %result );\n"
  1072. "@endtsexample\n\n"
  1073. "@see addText()\n"
  1074. "@see removeText()\n"
  1075. "@see addData()\n"
  1076. "@see getData()\n")
  1077. {
  1078. const char* text = object->getText();
  1079. if( !text )
  1080. return "";
  1081. return text;
  1082. }
  1083. void SimXMLDocument::removeText()
  1084. {
  1085. if(m_paNode.empty())
  1086. return;
  1087. const S32 iFinalElement = m_paNode.size() - 1;
  1088. TiXmlElement* pNode = m_paNode[iFinalElement];
  1089. if(!pNode)
  1090. return;
  1091. if( !pNode->FirstChild() )
  1092. return;
  1093. TiXmlText* text = pNode->FirstChild()->ToText();
  1094. if( !text )
  1095. return;
  1096. pNode->RemoveChild(text);
  1097. }
  1098. DefineEngineMethod( SimXMLDocument, removeText, void, (),,
  1099. "@brief Remove any text on the current Element.\n\n"
  1100. "Use getText() to retrieve any text from the current Element and addText() "
  1101. "to add text to the current Element. As getData() and addData() are equivalent "
  1102. "to getText() and addText(), removeText() will also remove any data from the "
  1103. "current Element.\n\n"
  1104. "@see addText()\n"
  1105. "@see getText()\n"
  1106. "@see addData()\n"
  1107. "@see getData()\n")
  1108. {
  1109. object->removeText();
  1110. }
  1111. void SimXMLDocument::addData(const char* text)
  1112. {
  1113. if(m_paNode.empty())
  1114. return;
  1115. const S32 iFinalElement = m_paNode.size() - 1;
  1116. TiXmlElement* pNode = m_paNode[iFinalElement];
  1117. if(!pNode)
  1118. return;
  1119. TiXmlText cText(text);
  1120. pNode->InsertEndChild( cText );
  1121. }
  1122. DefineEngineMethod( SimXMLDocument, addData, void, ( const char* text ),,
  1123. "@brief Add the given text as a child of current Element.\n\n"
  1124. "Use getData() to retrieve any text from the current Element.\n\n"
  1125. "addData() and addText() may be used interchangeably. As there is no "
  1126. "difference between data and text, you may also use removeText() to clear "
  1127. "any data from the current Element.\n\n"
  1128. "@param text String containing the text.\n\n"
  1129. "@tsexample\n"
  1130. "// Create a new XML document with a header and single element\n"
  1131. "// with some added data.\n"
  1132. "%x = new SimXMLDocument();\n"
  1133. "%x.addHeader();\n"
  1134. "%x.addNewElement(\"NewElement\");\n"
  1135. "%x.addData(\"Some text\");\n"
  1136. "%x.saveFile(\"test.xml\");\n\n"
  1137. "// Produces the following file:\n"
  1138. "// <?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>\n"
  1139. "// <NewElement>Some text</NewElement>\n"
  1140. "@endtsexample\n\n"
  1141. "@see getData()"
  1142. "@see addText()\n"
  1143. "@see getText()\n"
  1144. "@see removeText()\n")
  1145. {
  1146. object->addData( text );
  1147. }
  1148. const char* SimXMLDocument::getData()
  1149. {
  1150. if(m_paNode.empty())
  1151. return "";
  1152. const S32 iFinalElement = m_paNode.size() - 1;
  1153. TiXmlNode* pNode = m_paNode[iFinalElement];
  1154. if(!pNode)
  1155. return "";
  1156. if( !pNode->FirstChild() )
  1157. return "";
  1158. TiXmlText* text = pNode->FirstChild()->ToText();
  1159. if( !text )
  1160. return "";
  1161. return text->Value();
  1162. }
  1163. DefineEngineMethod( SimXMLDocument, getData, const char*, (),,
  1164. "@brief Gets the text from the current Element.\n\n"
  1165. "Use addData() to add text to the current Element.\n\n"
  1166. "getData() and getText() may be used interchangeably. As there is no "
  1167. "difference between data and text, you may also use removeText() to clear "
  1168. "any data from the current Element.\n\n"
  1169. "@return String containing the text in the current Element."
  1170. "@tsexample\n"
  1171. "// Using the following test.xml file as an example:\n"
  1172. "// <?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>\n"
  1173. "// <NewElement>Some data</NewElement>\n\n"
  1174. "// Load in the file\n"
  1175. "%x = new SimXMLDocument();\n"
  1176. "%x.loadFile(\"test.xml\");\n\n"
  1177. "// Make the first Element the current one\n"
  1178. "%x.pushFirstChildElement(\"NewElement\");\n\n"
  1179. "// Store the current Element's data ('Some data' in this example)\n"
  1180. "// into 'result'\n"
  1181. "%result = %x.getData();\n"
  1182. "echo( %result );\n"
  1183. "@endtsexample\n\n"
  1184. "@see addData()\n"
  1185. "@see addText()\n"
  1186. "@see getText()\n"
  1187. "@see removeText()\n")
  1188. {
  1189. const char* text = object->getData();
  1190. if( !text )
  1191. return "";
  1192. return text;
  1193. }
  1194. ////EOF/////////////////////////////////////////////////////////////////////////