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 <stdlib.h>
33 #include <sstream>
34
35 using std::string;
36 using std::ostringstream;
37
CXmlElement(_xmlNode * pXmlElement)38 CXmlElement::CXmlElement(_xmlNode* pXmlElement) : _pXmlElement(pXmlElement)
39 {
40 }
41
CXmlElement()42 CXmlElement::CXmlElement() : _pXmlElement(NULL)
43 {
44 }
45
setXmlElement(_xmlNode * pXmlElement)46 void CXmlElement::setXmlElement(_xmlNode* pXmlElement)
47 {
48 _pXmlElement = pXmlElement;
49 }
50
getType() const51 string CXmlElement::getType() const
52 {
53 return (const char*)_pXmlElement->name;
54 }
55
getPath() const56 string CXmlElement::getPath() const
57 {
58 string strPathElement = "/" + getType();
59
60 if (hasAttribute("Name")) {
61
62 strPathElement += "[@Name=" + getNameAttribute() + "]";
63 }
64
65 CXmlElement parentElement;
66
67 if (getParentElement(parentElement)) {
68
69 // Done
70 return parentElement.getPath() + strPathElement;
71 }
72 return strPathElement;
73 }
74
getNameAttribute() const75 string CXmlElement::getNameAttribute() const
76 {
77 return getAttributeString("Name");
78 }
79
hasAttribute(const string & strAttributeName) const80 bool CXmlElement::hasAttribute(const string& strAttributeName) const
81 {
82 return xmlHasProp(_pXmlElement, (const xmlChar*)strAttributeName.c_str()) != NULL;
83 }
84
getAttributeString(const string & strAttributeName) const85 string CXmlElement::getAttributeString(const string &strAttributeName) const
86 {
87 if (!hasAttribute(strAttributeName)) {
88
89 return "";
90 }
91 xmlChar* pucXmlValue = xmlGetProp((xmlNode*)_pXmlElement, (const xmlChar*)strAttributeName.c_str());
92 if (pucXmlValue == NULL) {
93 return "";
94 }
95
96 string strValue((const char*)pucXmlValue);
97
98 xmlFree(pucXmlValue);
99
100 return strValue;
101 }
102
getAttributeBoolean(const string & strAttributeName,const string & strTrueValue) const103 bool CXmlElement::getAttributeBoolean(const string& strAttributeName, const string& strTrueValue) const
104 {
105 return getAttributeString(strAttributeName) == strTrueValue;
106 }
107
getAttributeBoolean(const string & strAttributeName) const108 bool CXmlElement::getAttributeBoolean(const string& strAttributeName) const
109 {
110 string strAttributeValue(getAttributeString(strAttributeName));
111
112 return strAttributeValue == "true" || strAttributeValue == "1";
113 }
114
getAttributeInteger(const string & strAttributeName) const115 uint32_t CXmlElement::getAttributeInteger(const string &strAttributeName) const
116 {
117 string strAttributeValue(getAttributeString(strAttributeName));
118
119 return strtoul(strAttributeValue.c_str(), NULL, 0);
120 }
121
getAttributeSignedInteger(const string & strAttributeName) const122 int32_t CXmlElement::getAttributeSignedInteger(const string &strAttributeName) const
123 {
124 string strAttributeValue(getAttributeString(strAttributeName));
125
126 return strtol(strAttributeValue.c_str(), NULL, 0);
127 }
128
getAttributeDouble(const string & strAttributeName) const129 double CXmlElement::getAttributeDouble(const string &strAttributeName) const
130 {
131 string strAttributeValue(getAttributeString(strAttributeName));
132
133 return strtod(strAttributeValue.c_str(), NULL);
134 }
135
getTextContent() const136 string CXmlElement::getTextContent() const
137 {
138 xmlChar* pucXmlContent = xmlNodeGetContent(_pXmlElement);
139 if (pucXmlContent == NULL) {
140 return "";
141 }
142
143 string strContent((const char*)pucXmlContent);
144
145 xmlFree(pucXmlContent);
146
147 return strContent;
148 }
149
getChildElement(const string & strType,CXmlElement & childElement) const150 bool CXmlElement::getChildElement(const string& strType, CXmlElement& childElement) const
151 {
152 CChildIterator childIterator(*this);
153
154 while (childIterator.next(childElement)) {
155
156 if (childElement.getType() == strType) {
157
158 return true;
159 }
160 }
161 return false;
162 }
163
getChildElement(const string & strType,const string & strNameAttribute,CXmlElement & childElement) const164 bool CXmlElement::getChildElement(const string& strType, const string& strNameAttribute, CXmlElement& childElement) const
165 {
166 CChildIterator childIterator(*this);
167
168 while (childIterator.next(childElement)) {
169
170 if ((childElement.getType() == strType) && (childElement.getNameAttribute() == strNameAttribute)) {
171
172 return true;
173 }
174 }
175 return false;
176 }
177
getNbChildElements() const178 size_t CXmlElement::getNbChildElements() const
179 {
180 CXmlElement childElement;
181 size_t uiNbChildren = 0;
182
183 CChildIterator childIterator(*this);
184
185 while (childIterator.next(childElement)) {
186
187 uiNbChildren++;
188 }
189 return uiNbChildren;
190 }
191
getParentElement(CXmlElement & parentElement) const192 bool CXmlElement::getParentElement(CXmlElement& parentElement) const
193 {
194 _xmlNode* pXmlNode = _pXmlElement->parent;
195
196 if (pXmlNode->type == XML_ELEMENT_NODE) {
197
198 parentElement.setXmlElement(pXmlNode);
199
200 return true;
201 }
202 return false;
203 }
204
205 // Setters
setAttributeBoolean(const string & strAttributeName,bool bValue)206 void CXmlElement::setAttributeBoolean(const string& strAttributeName, bool bValue)
207 {
208 setAttributeString(strAttributeName, bValue ? "true" : "false");
209 }
210
211
setAttributeString(const string & strAttributeName,const string & strValue)212 void CXmlElement::setAttributeString(const string& strAttributeName, const string& strValue)
213 {
214 xmlNewProp(_pXmlElement, BAD_CAST strAttributeName.c_str(), BAD_CAST strValue.c_str());
215 }
216
setAttributeInteger(const string & strAttributeName,uint32_t uiValue)217 void CXmlElement::setAttributeInteger(const string& strAttributeName, uint32_t uiValue)
218 {
219 ostringstream strStream;
220 strStream << uiValue;
221 setAttributeString(strAttributeName, strStream.str());
222 }
223
setAttributeSignedInteger(const string & strAttributeName,int32_t iValue)224 void CXmlElement::setAttributeSignedInteger(const string& strAttributeName, int32_t iValue)
225 {
226 ostringstream strStream;
227 strStream << iValue;
228 setAttributeString(strAttributeName, strStream.str());
229 }
230
setNameAttribute(const string & strValue)231 void CXmlElement::setNameAttribute(const string& strValue)
232 {
233 setAttributeString("Name", strValue);
234 }
235
setTextContent(const string & strContent)236 void CXmlElement::setTextContent(const string& strContent)
237 {
238 xmlAddChild(_pXmlElement, xmlNewText(BAD_CAST strContent.c_str()));
239 }
240
241 // Child creation
createChild(CXmlElement & childElement,const string & strType)242 void CXmlElement::createChild(CXmlElement& childElement, const string& strType)
243 {
244 #ifdef LIBXML_TREE_ENABLED
245 xmlNodePtr pChildNode = xmlNewChild(_pXmlElement, NULL, BAD_CAST strType.c_str(), NULL);
246
247 childElement.setXmlElement(pChildNode);
248 #endif
249 }
250
251 // Child iteration
CChildIterator(const CXmlElement & xmlElement)252 CXmlElement::CChildIterator::CChildIterator(const CXmlElement& xmlElement) : _pCurNode(xmlElement._pXmlElement->children)
253 {
254 }
255
next(CXmlElement & xmlChildElement)256 bool CXmlElement::CChildIterator::next(CXmlElement& xmlChildElement)
257 {
258 while (_pCurNode) {
259
260 if (_pCurNode->type == XML_ELEMENT_NODE) {
261
262 xmlChildElement.setXmlElement(_pCurNode);
263
264 _pCurNode = _pCurNode->next;
265
266 return true;
267 }
268 _pCurNode = _pCurNode->next;
269 }
270
271 return false;
272 }
273
274