1 /*
2 * Copyright (c) 2011-2014, Intel Corporation
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation and/or
13 * other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors
16 * may be used to endorse or promote products derived from this software without
17 * specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30 #include "XmlElement.h"
31 #include <libxml/tree.h>
32 #include "convert.hpp"
33 #include <stdlib.h>
34
35 using std::string;
36
CXmlElement(_xmlNode * pXmlElement)37 CXmlElement::CXmlElement(_xmlNode *pXmlElement) : _pXmlElement(pXmlElement)
38 {
39 }
40
CXmlElement()41 CXmlElement::CXmlElement() : _pXmlElement(NULL)
42 {
43 }
44
setXmlElement(_xmlNode * pXmlElement)45 void CXmlElement::setXmlElement(_xmlNode *pXmlElement)
46 {
47 _pXmlElement = pXmlElement;
48 }
49
getType() const50 string CXmlElement::getType() const
51 {
52 return (const char *)_pXmlElement->name;
53 }
54
getPath() const55 string CXmlElement::getPath() const
56 {
57 string strPathElement = "/" + getType();
58
59 if (hasAttribute("Name")) {
60
61 strPathElement += "[@Name=" + getNameAttribute() + "]";
62 }
63
64 CXmlElement parentElement;
65
66 if (getParentElement(parentElement)) {
67
68 // Done
69 return parentElement.getPath() + strPathElement;
70 }
71 return strPathElement;
72 }
73
hasAttribute(const string & strAttributeName) const74 bool CXmlElement::hasAttribute(const string &strAttributeName) const
75 {
76 return xmlHasProp(_pXmlElement, (const xmlChar *)strAttributeName.c_str()) != NULL;
77 }
78
79 template <>
getAttribute(const string & name,string & value) const80 bool CXmlElement::getAttribute<std::string>(const string &name, string &value) const
81 {
82 if (!hasAttribute(name)) {
83 return false;
84 }
85
86 string backup = value;
87 xmlChar *pucXmlValue = xmlGetProp((xmlNode *)_pXmlElement, (const xmlChar *)name.c_str());
88 if (pucXmlValue == NULL) {
89 value = backup;
90 return false;
91 }
92
93 value = (const char *)pucXmlValue;
94
95 xmlFree(pucXmlValue);
96
97 return true;
98 }
99
100 template <typename T>
getAttribute(const std::string & name,T & value) const101 bool CXmlElement::getAttribute(const std::string &name, T &value) const
102 {
103 std::string rawValue;
104 if (!getAttribute(name, rawValue)) {
105 return false;
106 }
107
108 T backup = value;
109 if (!convertTo<T>(rawValue, value)) {
110 value = backup;
111 return false;
112 }
113
114 return true;
115 }
116
getNameAttribute() const117 string CXmlElement::getNameAttribute() const
118 {
119 string attribute;
120 getAttribute("Name", attribute);
121 return attribute;
122 }
123
getTextContent() const124 string CXmlElement::getTextContent() const
125 {
126 xmlChar *pucXmlContent = xmlNodeGetContent(_pXmlElement);
127 if (pucXmlContent == NULL) {
128 return "";
129 }
130
131 string strContent((const char *)pucXmlContent);
132
133 xmlFree(pucXmlContent);
134
135 return strContent;
136 }
137
getChildElement(const string & strType,CXmlElement & childElement) const138 bool CXmlElement::getChildElement(const string &strType, CXmlElement &childElement) const
139 {
140 CChildIterator childIterator(*this);
141
142 while (childIterator.next(childElement)) {
143
144 if (childElement.getType() == strType) {
145
146 return true;
147 }
148 }
149 return false;
150 }
151
getChildElement(const string & strType,const string & strNameAttribute,CXmlElement & childElement) const152 bool CXmlElement::getChildElement(const string &strType, const string &strNameAttribute,
153 CXmlElement &childElement) const
154 {
155 CChildIterator childIterator(*this);
156
157 while (childIterator.next(childElement)) {
158
159 if ((childElement.getType() == strType) &&
160 (childElement.getNameAttribute() == strNameAttribute)) {
161
162 return true;
163 }
164 }
165 return false;
166 }
167
getNbChildElements() const168 size_t CXmlElement::getNbChildElements() const
169 {
170 CXmlElement childElement;
171 size_t uiNbChildren = 0;
172
173 CChildIterator childIterator(*this);
174
175 while (childIterator.next(childElement)) {
176
177 uiNbChildren++;
178 }
179 return uiNbChildren;
180 }
181
getParentElement(CXmlElement & parentElement) const182 bool CXmlElement::getParentElement(CXmlElement &parentElement) const
183 {
184 _xmlNode *pXmlNode = _pXmlElement->parent;
185
186 if (pXmlNode->type == XML_ELEMENT_NODE) {
187
188 parentElement.setXmlElement(pXmlNode);
189
190 return true;
191 }
192 return false;
193 }
194
195 template <>
setAttribute(const string & name,const bool & value)196 void CXmlElement::setAttribute<bool>(const string &name, const bool &value)
197 {
198 setAttribute(name, value ? "true" : "false");
199 }
200
201 template <>
setAttribute(const string & name,const string & value)202 void CXmlElement::setAttribute<std::string>(const string &name, const string &value)
203 {
204 setAttribute(name, value.c_str());
205 }
206
207 // This method exists for 2 reasons:
208 // - at link time, all calls to setAttribute(const string&, const char [N])
209 // for any value of N will all resolve to this method; this prevents the
210 // need for one template instance per value of N.
211 // - the libxml2 API takes a C-style string anyway.
setAttribute(const string & name,const char * value)212 void CXmlElement::setAttribute(const string &name, const char *value)
213 {
214 xmlNewProp(_pXmlElement, BAD_CAST name.c_str(), BAD_CAST value);
215 }
216
217 template <typename T>
setAttribute(const std::string & name,const T & value)218 void CXmlElement::setAttribute(const std::string &name, const T &value)
219 {
220 setAttribute(name, std::to_string(value).c_str());
221 }
222
setNameAttribute(const string & strValue)223 void CXmlElement::setNameAttribute(const string &strValue)
224 {
225 setAttribute("Name", strValue);
226 }
227
setTextContent(const string & strContent)228 void CXmlElement::setTextContent(const string &strContent)
229 {
230 xmlAddChild(_pXmlElement, xmlNewText(BAD_CAST strContent.c_str()));
231 }
232
233 // Child creation
createChild(CXmlElement & childElement,const string & strType)234 void CXmlElement::createChild(CXmlElement &childElement, const string &strType)
235 {
236 #ifdef LIBXML_TREE_ENABLED
237 xmlNodePtr pChildNode = xmlNewChild(_pXmlElement, NULL, BAD_CAST strType.c_str(), NULL);
238
239 childElement.setXmlElement(pChildNode);
240 #endif
241 }
242
243 // Child iteration
CChildIterator(const CXmlElement & xmlElement)244 CXmlElement::CChildIterator::CChildIterator(const CXmlElement &xmlElement)
245 : _pCurNode(xmlElement._pXmlElement->children)
246 {
247 }
248
next(CXmlElement & xmlChildElement)249 bool CXmlElement::CChildIterator::next(CXmlElement &xmlChildElement)
250 {
251 while (_pCurNode) {
252
253 if (_pCurNode->type == XML_ELEMENT_NODE) {
254
255 xmlChildElement.setXmlElement(_pCurNode);
256
257 _pCurNode = _pCurNode->next;
258
259 return true;
260 }
261 _pCurNode = _pCurNode->next;
262 }
263
264 return false;
265 }
266
267 template bool CXmlElement::getAttribute(const std::string &name, std::string &value) const;
268 template bool CXmlElement::getAttribute(const std::string &name, bool &value) const;
269 template bool CXmlElement::getAttribute(const std::string &name, short &value) const;
270 template bool CXmlElement::getAttribute(const std::string &name, unsigned short &value) const;
271 template bool CXmlElement::getAttribute(const std::string &name, int &value) const;
272 template bool CXmlElement::getAttribute(const std::string &name, unsigned int &value) const;
273 template bool CXmlElement::getAttribute(const std::string &name, long &value) const;
274 template bool CXmlElement::getAttribute(const std::string &name, unsigned long &value) const;
275 template bool CXmlElement::getAttribute(const std::string &name, long long &value) const;
276 template bool CXmlElement::getAttribute(const std::string &name, unsigned long long &value) const;
277 template bool CXmlElement::getAttribute(const std::string &name, float &value) const;
278 template bool CXmlElement::getAttribute(const std::string &name, double &value) const;
279
280 template void CXmlElement::setAttribute(const std::string &name, const std::string &value);
281 template void CXmlElement::setAttribute(const std::string &name, const bool &value);
282 template void CXmlElement::setAttribute(const std::string &name, const short &value);
283 template void CXmlElement::setAttribute(const std::string &name, const unsigned short &value);
284 template void CXmlElement::setAttribute(const std::string &name, const int &value);
285 template void CXmlElement::setAttribute(const std::string &name, const unsigned int &value);
286 template void CXmlElement::setAttribute(const std::string &name, const long &value);
287 template void CXmlElement::setAttribute(const std::string &name, const unsigned long &value);
288 template void CXmlElement::setAttribute(const std::string &name, const long long &value);
289 template void CXmlElement::setAttribute(const std::string &name, const unsigned long long &value);
290 template void CXmlElement::setAttribute(const std::string &name, const float &value);
291 template void CXmlElement::setAttribute(const std::string &name, const double &value);
292