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.
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.
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>
26 #include <LibC/LibC.h>
28 using namespace GenNS
;
30 XMLAttribute::XMLAttribute()
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
)
55 void XMLAttribute::Initialize(const char* sN
, int64 sV
)
61 String
&XMLAttribute::GetName()
66 String
&XMLAttribute::GetValue()
71 void XMLAttribute::SetName(const char* 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()
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
)
109 bool XMLElement::freeNode(XMLElement
* const& node
)
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
)
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
);
149 XMLAttribute
*XMLElement::AddAttribute(const char* sName
, const char* sValue
)
151 XMLAttribute
*pNew
= new XMLAttribute(sName
, sValue
);
156 XMLAttribute
*XMLElement::AddAttribute(const char* sNm
, int64 lVal
)
158 XMLAttribute
*pNew
= new XMLAttribute(sNm
, lVal
);
163 XMLElement
*XMLElement::AddChild(XMLElement
* pElem
)
169 XMLAttribute
*XMLElement::AddAttribute(XMLAttribute
*pAttr
)
171 hAttributes
<< pAttr
;
175 void XMLElement::RemChild(XMLElement
* 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
))
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
];
205 String
*XMLElement::GetChildValue(const char *sName
)
207 XMLElement
*pElem
= FindChild(sName
);
210 return &pElem
->GetValue();
213 String
*XMLElement::GetAttributeValue(const char *sName
)
215 XMLAttribute
*pAttr
= FindAttribute(sName
);
218 return &pAttr
->GetValue();
223 XMLDocument::XMLDocument()
228 pExpat
= Expat2IFace::GetInstance(0);
231 XMLDocument::XMLDocument(const char *sName
)
232 : XMLElement(sName
, "")
237 pExpat
= Expat2IFace::GetInstance(0);
240 XMLDocument::~XMLDocument()
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
)
269 // MessageBox("Info", "On Start: %s", "Ok", ARRAY((int)name));
271 level
= hParse
.Count();
275 pLast
= hParse
[level
-1]->AddChild((char*)name
, "");
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());
291 // MessageBox("Info", "Done Start: %s", "Ok", ARRAY((int)name));
294 void XMLDocument::XMLEndHandler(const XML_Char
*name
)
297 // MessageBox("Info", "On End: %s", "Ok", ARRAY((int)name));
298 if (hParse
.Count() == 0)
300 eError
= XErr_CorruptedXML
;
303 pLast
= hParse
[hParse
.Count()-1];
305 String s
= pLast
->GetValue();
307 pLast
->SetValue(s
.Data());
309 XMLElement
*pElem
= hParse
[(hParse
.Count() - 1)];
311 // MessageBox("Info", "Done End: %s", "Ok", ARRAY((int)name));
314 void XMLDocument::XMLContentHandler(const XML_Char
*begin
, int length
)
318 // MessageBox("Info", "On Content", "Ok", 0);
320 if (hParse
.Count() == 0)
322 eError
= XErr_CorruptedXML
;
325 pLast
= hParse
[hParse
.Count()-1]; // get last element
329 // 1. get current data
330 s1
= pLast
->GetValue();
333 char *pBuff
= new char[length
+1];
335 strncpy(pBuff
, begin
, length
);
337 // 3. concatenate two strings
342 pLast
->SetValue(s1
.Data());
343 // MessageBox("Info", "Done Content", "Ok", 0);
346 bool XMLDocument::ReadXML(const char *sName
)
352 ASSERT(NULL
!= pExpat
);
355 eError
= XErr_NoExpat
;
360 ASSERT(sFileName
.Length() != 0);
361 if (sFileName
.Length() == 0)
363 eError
= XErr_NoFile
;
371 pExpat
->XML_ParserFree(pParser
);
375 fh
= DOS
->Open(sFileName
.Data(), MODE_OLDFILE
);
378 eError
= XErr_NoFile
;
383 pParser
= pExpat
->XML_ParserCreate(0);
384 ASSERT(0 != pParser
);
388 eError
= XErr_NoParser
;
393 pExpat
->XML_SetUserData(pParser
, this);
394 pExpat
->XML_SetElementHandler(pParser
, &XMLDocument::fXMLStartHandler
, &XMLDocument::fXMLEndHandler
);
395 pExpat
->XML_SetCharacterDataHandler(pParser
, &XMLDocument::fXMLContentHandler
);
400 mem
= pExpat
->XML_GetBuffer(pParser
, 8192);
403 len
= DOS
->Read(fh
, mem
, 8192);
404 pExpat
->XML_ParseBuffer(pParser
, len
, 0 == len
);
408 eError
= XErr_NoMemory
;
415 pExpat
->XML_ParserFree(pParser
);
417 if (eError
== XErr_OK
)
422 bool XMLDocument::WriteXML(const char *sName
)
427 if (sFileName
.Length() == 0)
429 eError
= XErr_NoFile
;
435 fh
= DOS
->Open(sFileName
.Data(), MODE_NEWFILE
);
438 eError
= XErr_NoFile
;
442 DOS
->FPuts(fh
, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
444 XMLWriteElement(fh
, this);
447 if (eError
== XErr_OK
)
452 /* FIXME: polaczyc w jedno */
454 bool XMLDocument::ReadXML(BPTR fh
)
459 ASSERT(NULL
!= pExpat
);
462 eError
= XErr_NoExpat
;
470 pExpat
->XML_ParserFree(pParser
);
476 eError
= XErr_NoFile
;
482 pParser
= pExpat
->XML_ParserCreate(0);
483 ASSERT(0 != pParser
);
487 eError
= XErr_NoParser
;
492 pExpat
->XML_SetUserData(pParser
, this);
493 pExpat
->XML_SetElementHandler(pParser
, &XMLDocument::fXMLStartHandler
, &XMLDocument::fXMLEndHandler
);
494 pExpat
->XML_SetCharacterDataHandler(pParser
, &XMLDocument::fXMLContentHandler
);
499 mem
= pExpat
->XML_GetBuffer(pParser
, 8192);
502 len
= DOS
->Read(fh
, mem
, 8192);
503 if (0 != pExpat
->XML_ParseBuffer(pParser
, len
, 0 == len
))
505 eError
= XErr_CorruptedXML
;
511 eError
= XErr_NoMemory
;
517 pExpat
->XML_ParserFree(pParser
);
519 if (eError
== XErr_OK
)
524 bool XMLDocument::WriteXML(BPTR fh
)
530 eError
= XErr_NoFile
;
534 DOS
->FPuts(fh
, "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n");
536 XMLWriteElement(fh
, this);
538 if (eError
== XErr_OK
)
543 void XMLDocument::XMLWriteElement(BPTR fh
, XMLElement
* pElem
)
545 for (int i
=0; i
<level
; i
++)
546 DOS
->FPuts(fh
, "\t");
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("&", "&");
555 val
.Substitute("'", "'");
556 val
.Substitute("\"", """);
557 val
.Substitute("<", "<");
558 val
.Substitute(">", ">");
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();
573 val
.Substitute("&", "&");
574 val
.Substitute("'", "'");
575 val
.Substitute("\"", """);
576 val
.Substitute("<", "<");
577 val
.Substitute(">", ">");
580 DOS
->FPuts(fh
, (char*)(val
.ToUTF8()));
584 // it is all clear, we just close xml tag.
585 DOS
->FPuts(fh
, " />\n");
591 DOS
->FPuts(fh
, ">\n");
593 for (long i
=0; i
<pElem
->GetChildrenCount(); i
++)
595 XMLElement
*pEl
= pElem
->GetChild(i
);
596 XMLWriteElement(fh
, pEl
);
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()