Adapted to recent changes of %build_linklib.
[AROS-Contrib.git] / FryingPan / framework / Generic / XMLDocument.cpp
blob97bb77b5c523518629d228c62d9ab1d807ed2ab2
1 /*
2 * Amiga Generic Set - set of libraries and includes to ease sw development for all Amiga platforms
3 * Copyright (C) 2001-2011 Tomasz Wiszkowski Tomasz.Wiszkowski at gmail.com.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library 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 GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 #include "XMLDocument.h"
22 #include <libclass/expat.h>
23 #include <libdata/expat.h>
24 #include <libclass/dos.h>
25 #include <dos/dos.h>
26 #include <LibC/LibC.h>
28 using namespace GenNS;
30 XMLAttribute::XMLAttribute()
32 Initialize("", "");
35 XMLAttribute::XMLAttribute(const char* sName, const char* sValue)
37 Initialize(sName, sValue);
40 XMLAttribute::XMLAttribute(const char* sName, int64 sValue)
42 Initialize(sName, sValue);
45 XMLAttribute::~XMLAttribute()
49 void XMLAttribute::Initialize(const char* sN, const char* sV)
51 sName = sN;
52 sValue = sV;
55 void XMLAttribute::Initialize(const char* sN, int64 sV)
57 sName = sN;
58 sValue = sV;
61 String &XMLAttribute::GetName()
63 return sName;
66 String &XMLAttribute::GetValue()
68 return sValue;
71 void XMLAttribute::SetName(const char* sName)
73 this->sName = sName;
76 void XMLAttribute::SetValue(const char* sValue)
78 this->sValue = sValue;
81 void XMLAttribute::SetValue(uint64 sValue)
83 this->sValue = sValue;
87 XMLElement::XMLElement()
89 Initialize("", "");
92 XMLElement::XMLElement(const char* sName, const char* sValue)
94 Initialize(sName, sValue);
97 XMLElement::~XMLElement()
99 hAttributes.ForEach(&XMLElement::freeAttr);
100 hChildren.ForEach(&XMLElement::freeNode);
103 bool XMLElement::freeAttr(XMLAttribute* const& attr)
105 delete attr;
106 return true;
109 bool XMLElement::freeNode(XMLElement* const& node)
111 delete node;
112 return true;
115 void XMLElement::Initialize(const char* sN, const char* sV)
117 XMLAttribute::Initialize(sN, sV);
118 hChildren.Empty(); // ensure its empty
119 hAttributes.Empty(); // !!
122 long XMLElement::GetChildrenCount()
124 return hChildren.Count();
127 XMLElement *XMLElement::GetChild(long i)
129 return hChildren[i];
132 long XMLElement::GetAttributesCount()
134 return hAttributes.Count();
137 XMLAttribute *XMLElement::GetAttribute(long i)
139 return hAttributes[i];
142 XMLElement *XMLElement::AddChild(const char* sName, const char* sValue)
144 XMLElement *pNew = new XMLElement(sName, sValue);
145 hChildren << pNew;
146 return pNew;
149 XMLAttribute *XMLElement::AddAttribute(const char* sName, const char* sValue)
151 XMLAttribute *pNew = new XMLAttribute(sName, sValue);
152 hAttributes << pNew;
153 return pNew;
156 XMLAttribute *XMLElement::AddAttribute(const char* sNm, int64 lVal)
158 XMLAttribute *pNew = new XMLAttribute(sNm, lVal);
159 hAttributes << pNew;
160 return pNew;
163 XMLElement *XMLElement::AddChild(XMLElement* pElem)
165 hChildren << pElem;
166 return pElem;
169 XMLAttribute *XMLElement::AddAttribute(XMLAttribute *pAttr)
171 hAttributes << pAttr;
172 return pAttr;
175 void XMLElement::RemChild(XMLElement* pElem)
177 hChildren >> pElem;
180 void XMLElement::RemAttribute(XMLAttribute* pAttr)
182 hAttributes >> pAttr;
185 XMLElement *XMLElement::FindChild(const char* sName)
187 for (int i=0; i<hChildren.Count(); i++)
189 if (hChildren[i]->GetName().Equals(sName))
190 return hChildren[i];
192 return 0;
195 XMLAttribute *XMLElement::FindAttribute(const char* sName)
197 for (int i=0; i<hAttributes.Count(); i++)
199 if (hAttributes[i]->GetName().Equals(sName))
200 return hAttributes[i];
202 return 0;
205 String *XMLElement::GetChildValue(const char *sName)
207 XMLElement *pElem = FindChild(sName);
208 if (0 == pElem)
209 return 0;
210 return &pElem->GetValue();
213 String *XMLElement::GetAttributeValue(const char *sName)
215 XMLAttribute *pAttr = FindAttribute(sName);
216 if (0 == pAttr)
217 return 0;
218 return &pAttr->GetValue();
223 XMLDocument::XMLDocument()
225 pParser = 0;
226 eError = XErr_OK;
227 sFileName = "";
228 pExpat = Expat2IFace::GetInstance(0);
231 XMLDocument::XMLDocument(const char *sName)
232 : XMLElement(sName, "")
234 pParser = 0;
235 eError = XErr_OK;
236 sFileName = "";
237 pExpat = Expat2IFace::GetInstance(0);
240 XMLDocument::~XMLDocument()
242 if (pExpat)
244 if (pParser)
245 pExpat->XML_ParserFree(pParser);
246 pExpat->FreeInstance();
250 void XMLDocument::fXMLStartHandler(void* userData, const XML_Char *name, const XML_Char **atts)
252 ((XMLDocument*)userData)->XMLStartHandler(name, atts);
255 void XMLDocument::fXMLEndHandler(void* userData, const XML_Char *name)
257 ((XMLDocument*)userData)->XMLEndHandler(name);
260 void XMLDocument::fXMLContentHandler(void* userData, const XML_Char *begin, int length)
262 ((XMLDocument*)userData)->XMLContentHandler(begin, length);
265 void XMLDocument::XMLStartHandler(const XML_Char *name, const XML_Char **atts)
267 XMLElement *pLast;
269 // MessageBox("Info", "On Start: %s", "Ok", ARRAY((int)name));
271 level = hParse.Count();
273 if (0 != level)
275 pLast = hParse[level-1]->AddChild((char*)name, "");
277 else
279 pLast = this;
280 Initialize((char*)name, ""); // implies: free(!)
283 for (int i=0; 0 != atts[i]; i+=2)
285 String s((char*)(atts[i+1]));
286 pLast->AddAttribute((char*)atts[i], s.FromUTF8().Data());
289 hParse << pLast;
291 // MessageBox("Info", "Done Start: %s", "Ok", ARRAY((int)name));
294 void XMLDocument::XMLEndHandler(const XML_Char *name)
296 XMLElement *pLast;
297 // MessageBox("Info", "On End: %s", "Ok", ARRAY((int)name));
298 if (hParse.Count() == 0)
300 eError = XErr_CorruptedXML;
301 return;
303 pLast = hParse[hParse.Count()-1];
305 String s = pLast->GetValue();
306 s.FromUTF8();
307 pLast->SetValue(s.Data());
309 XMLElement *pElem = hParse[(hParse.Count() - 1)];
310 hParse >> pElem;
311 // MessageBox("Info", "Done End: %s", "Ok", ARRAY((int)name));
314 void XMLDocument::XMLContentHandler(const XML_Char *begin, int length)
316 XMLElement *pLast;
318 // MessageBox("Info", "On Content", "Ok", 0);
320 if (hParse.Count() == 0)
322 eError = XErr_CorruptedXML;
323 return;
325 pLast = hParse[hParse.Count()-1]; // get last element
327 String s1;
329 // 1. get current data
330 s1 = pLast->GetValue();
332 // 2. get new data
333 char *pBuff = new char[length+1];
334 pBuff[length] = 0;
335 strncpy(pBuff, begin, length);
337 // 3. concatenate two strings
338 s1 += pBuff;
339 delete [] pBuff;
341 // 4. set new data
342 pLast->SetValue(s1.Data());
343 // MessageBox("Info", "Done Content", "Ok", 0);
346 bool XMLDocument::ReadXML(const char *sName)
348 BPTR fh = 0;
349 void *mem;
350 int len;
352 ASSERT(NULL != pExpat);
353 if (0 == pExpat)
355 eError = XErr_NoExpat;
356 return false;
359 sFileName = sName;
360 ASSERT(sFileName.Length() != 0);
361 if (sFileName.Length() == 0)
363 eError = XErr_NoFile;
364 return false;
367 eError = XErr_OK;
368 level = 0;
370 if (pParser)
371 pExpat->XML_ParserFree(pParser);
373 pParser = 0;
375 fh = DOS->Open(sFileName.Data(), MODE_OLDFILE);
376 if (fh == 0)
378 eError = XErr_NoFile;
379 return false;
382 ASSERT(0 != fh);
383 pParser = pExpat->XML_ParserCreate(0);
384 ASSERT(0 != pParser);
385 if (pParser == 0)
387 DOS->Close(fh);
388 eError = XErr_NoParser;
389 return false;
392 hParse.Empty();
393 pExpat->XML_SetUserData(pParser, this);
394 pExpat->XML_SetElementHandler(pParser, &XMLDocument::fXMLStartHandler, &XMLDocument::fXMLEndHandler);
395 pExpat->XML_SetCharacterDataHandler(pParser, &XMLDocument::fXMLContentHandler);
399 len = 0;
400 mem = pExpat->XML_GetBuffer(pParser, 8192);
401 if (mem)
403 len = DOS->Read(fh, mem, 8192);
404 pExpat->XML_ParseBuffer(pParser, len, 0 == len);
406 else
408 eError = XErr_NoMemory;
409 break;
412 while (0 != len);
414 DOS->Close(fh);
415 pExpat->XML_ParserFree(pParser);
416 pParser = 0;
417 if (eError == XErr_OK)
418 return true;
419 return false;
422 bool XMLDocument::WriteXML(const char *sName)
424 BPTR fh = 0;
426 sFileName = sName;
427 if (sFileName.Length() == 0)
429 eError = XErr_NoFile;
430 return false;
433 eError = XErr_OK;
435 fh = DOS->Open(sFileName.Data(), MODE_NEWFILE);
436 if (fh == 0)
438 eError = XErr_NoFile;
439 return false;
442 DOS->FPuts(fh, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
443 level = 0;
444 XMLWriteElement(fh, this);
446 DOS->Close(fh);
447 if (eError == XErr_OK)
448 return true;
449 return false;
452 /* FIXME: polaczyc w jedno */
454 bool XMLDocument::ReadXML(BPTR fh)
456 void *mem;
457 int len;
459 ASSERT(NULL != pExpat);
460 if (0 == pExpat)
462 eError = XErr_NoExpat;
463 return false;
466 eError = XErr_OK;
467 level = 0;
469 if (pParser)
470 pExpat->XML_ParserFree(pParser);
472 pParser = 0;
474 if (fh == 0)
476 eError = XErr_NoFile;
477 return false;
481 ASSERT(0 != fh);
482 pParser = pExpat->XML_ParserCreate(0);
483 ASSERT(0 != pParser);
484 if (pParser == 0)
486 DOS->Close(fh);
487 eError = XErr_NoParser;
488 return false;
491 hParse.Empty();
492 pExpat->XML_SetUserData(pParser, this);
493 pExpat->XML_SetElementHandler(pParser, &XMLDocument::fXMLStartHandler, &XMLDocument::fXMLEndHandler);
494 pExpat->XML_SetCharacterDataHandler(pParser, &XMLDocument::fXMLContentHandler);
498 len = 0;
499 mem = pExpat->XML_GetBuffer(pParser, 8192);
500 if (mem)
502 len = DOS->Read(fh, mem, 8192);
503 if (0 != pExpat->XML_ParseBuffer(pParser, len, 0 == len))
505 eError = XErr_CorruptedXML;
506 break;
509 else
511 eError = XErr_NoMemory;
512 break;
515 while (0 != len);
517 pExpat->XML_ParserFree(pParser);
518 pParser = 0;
519 if (eError == XErr_OK)
520 return true;
521 return false;
524 bool XMLDocument::WriteXML(BPTR fh)
526 eError = XErr_OK;
528 if (fh == 0)
530 eError = XErr_NoFile;
531 return false;
534 DOS->FPuts(fh, "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n");
535 level = 0;
536 XMLWriteElement(fh, this);
538 if (eError == XErr_OK)
539 return true;
540 return false;
543 void XMLDocument::XMLWriteElement(BPTR fh, XMLElement* pElem)
545 for (int i=0; i<level; i++)
546 DOS->FPuts(fh, "\t");
547 DOS->FPuts(fh, "<");
548 DOS->FPuts(fh, (char*)pElem->GetName());
549 for (long i=0; i<pElem->GetAttributesCount(); i++)
551 XMLAttribute *pAttr = pElem->GetAttribute(i);
552 String val = pAttr->GetValue();
554 val.Substitute("&", "&amp;");
555 val.Substitute("'", "&apos;");
556 val.Substitute("\"", "&quot;");
557 val.Substitute("<", "&lt;");
558 val.Substitute(">", "&gt;");
560 DOS->FPuts(fh, " ");
561 DOS->FPuts(fh, (char*)pAttr->GetName());
562 DOS->FPuts(fh, "=\"");
563 DOS->FPuts(fh, (char*)(val.ToUTF8()));
564 DOS->FPuts(fh, "\"");
567 if (0 == pElem->GetChildrenCount())
569 if (0 != strlen(pElem->GetValue()))
571 String val = pElem->GetValue();
572 // we pust the data.
573 val.Substitute("&", "&amp;");
574 val.Substitute("'", "&apos;");
575 val.Substitute("\"", "&quot;");
576 val.Substitute("<", "&lt;");
577 val.Substitute(">", "&gt;");
579 DOS->FPuts(fh, ">");
580 DOS->FPuts(fh, (char*)(val.ToUTF8()));
582 else
584 // it is all clear, we just close xml tag.
585 DOS->FPuts(fh, " />\n");
586 return;
589 else
591 DOS->FPuts(fh, ">\n");
592 ++level;
593 for (long i=0; i<pElem->GetChildrenCount(); i++)
595 XMLElement *pEl = pElem->GetChild(i);
596 XMLWriteElement(fh, pEl);
598 --level;
599 for (int i=0; i<level; i++)
600 DOS->FPuts(fh, "\t");
602 DOS->FPuts(fh, "</");
603 DOS->FPuts(fh, (char*)pElem->GetName());
604 DOS->FPuts(fh, ">\n");
607 XMLDocument::XMLError XMLDocument::GetError()
609 return eError;