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 38 CXmlElement::CXmlElement(_xmlNode* pXmlElement) : _pXmlElement(pXmlElement) 39 { 40 } 41 42 CXmlElement::CXmlElement() : _pXmlElement(NULL) 43 { 44 } 45 46 void CXmlElement::setXmlElement(_xmlNode* pXmlElement) 47 { 48 _pXmlElement = pXmlElement; 49 } 50 51 string CXmlElement::getType() const 52 { 53 return (const char*)_pXmlElement->name; 54 } 55 56 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 75 string CXmlElement::getNameAttribute() const 76 { 77 return getAttributeString("Name"); 78 } 79 80 bool CXmlElement::hasAttribute(const string& strAttributeName) const 81 { 82 return xmlHasProp(_pXmlElement, (const xmlChar*)strAttributeName.c_str()) != NULL; 83 } 84 85 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 103 bool CXmlElement::getAttributeBoolean(const string& strAttributeName, const string& strTrueValue) const 104 { 105 return getAttributeString(strAttributeName) == strTrueValue; 106 } 107 108 bool CXmlElement::getAttributeBoolean(const string& strAttributeName) const 109 { 110 string strAttributeValue(getAttributeString(strAttributeName)); 111 112 return strAttributeValue == "true" || strAttributeValue == "1"; 113 } 114 115 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 122 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 129 double CXmlElement::getAttributeDouble(const string &strAttributeName) const 130 { 131 string strAttributeValue(getAttributeString(strAttributeName)); 132 133 return strtod(strAttributeValue.c_str(), NULL); 134 } 135 136 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 150 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 164 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 178 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 192 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 206 void CXmlElement::setAttributeBoolean(const string& strAttributeName, bool bValue) 207 { 208 setAttributeString(strAttributeName, bValue ? "true" : "false"); 209 } 210 211 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 217 void CXmlElement::setAttributeInteger(const string& strAttributeName, uint32_t uiValue) 218 { 219 ostringstream strStream; 220 strStream << uiValue; 221 setAttributeString(strAttributeName, strStream.str()); 222 } 223 224 void CXmlElement::setAttributeSignedInteger(const string& strAttributeName, int32_t iValue) 225 { 226 ostringstream strStream; 227 strStream << iValue; 228 setAttributeString(strAttributeName, strStream.str()); 229 } 230 231 void CXmlElement::setNameAttribute(const string& strValue) 232 { 233 setAttributeString("Name", strValue); 234 } 235 236 void CXmlElement::setTextContent(const string& strContent) 237 { 238 xmlAddChild(_pXmlElement, xmlNewText(BAD_CAST strContent.c_str())); 239 } 240 241 // Child creation 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 252 CXmlElement::CChildIterator::CChildIterator(const CXmlElement& xmlElement) : _pCurNode(xmlElement._pXmlElement->children) 253 { 254 } 255 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