xmlelement.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  1. /*
  2. * Copyright 2004 The WebRTC Project Authors. All rights reserved.
  3. *
  4. * Use of this source code is governed by a BSD-style license
  5. * that can be found in the LICENSE file in the root of the source
  6. * tree. An additional intellectual property rights grant can be found
  7. * in the file PATENTS. All contributing project authors may
  8. * be found in the AUTHORS file in the root of the source tree.
  9. */
  10. #include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
  11. #include <ostream>
  12. #include <sstream>
  13. #include <string>
  14. #include <vector>
  15. #include "base/check.h"
  16. #include "third_party/libjingle_xmpp/xmllite/qname.h"
  17. #include "third_party/libjingle_xmpp/xmllite/xmlbuilder.h"
  18. #include "third_party/libjingle_xmpp/xmllite/xmlconstants.h"
  19. #include "third_party/libjingle_xmpp/xmllite/xmlparser.h"
  20. #include "third_party/libjingle_xmpp/xmllite/xmlprinter.h"
  21. namespace jingle_xmpp {
  22. XmlChild::~XmlChild() {
  23. }
  24. bool XmlText::IsTextImpl() const {
  25. return true;
  26. }
  27. XmlElement* XmlText::AsElementImpl() const {
  28. return NULL;
  29. }
  30. XmlText* XmlText::AsTextImpl() const {
  31. return const_cast<XmlText *>(this);
  32. }
  33. void XmlText::SetText(const std::string& text) {
  34. text_ = text;
  35. }
  36. void XmlText::AddParsedText(const char* buf, int len) {
  37. text_.append(buf, len);
  38. }
  39. void XmlText::AddText(const std::string& text) {
  40. text_ += text;
  41. }
  42. XmlText::~XmlText() {
  43. }
  44. XmlElement::XmlElement(const QName& name) :
  45. name_(name),
  46. first_attr_(NULL),
  47. last_attr_(NULL),
  48. first_child_(NULL),
  49. last_child_(NULL),
  50. cdata_(false) {
  51. }
  52. XmlElement::XmlElement(const XmlElement& elt) :
  53. XmlChild(),
  54. name_(elt.name_),
  55. first_attr_(NULL),
  56. last_attr_(NULL),
  57. first_child_(NULL),
  58. last_child_(NULL),
  59. cdata_(false) {
  60. // copy attributes
  61. XmlAttr* attr;
  62. XmlAttr ** plast_attr = &first_attr_;
  63. XmlAttr* newAttr = NULL;
  64. for (attr = elt.first_attr_; attr; attr = attr->NextAttr()) {
  65. newAttr = new XmlAttr(*attr);
  66. *plast_attr = newAttr;
  67. plast_attr = &(newAttr->next_attr_);
  68. }
  69. last_attr_ = newAttr;
  70. // copy children
  71. XmlChild* pChild;
  72. XmlChild ** ppLast = &first_child_;
  73. XmlChild* newChild = NULL;
  74. for (pChild = elt.first_child_; pChild; pChild = pChild->NextChild()) {
  75. if (pChild->IsText()) {
  76. newChild = new XmlText(*(pChild->AsText()));
  77. } else {
  78. newChild = new XmlElement(*(pChild->AsElement()));
  79. }
  80. *ppLast = newChild;
  81. ppLast = &(newChild->next_child_);
  82. }
  83. last_child_ = newChild;
  84. cdata_ = elt.cdata_;
  85. }
  86. XmlElement::XmlElement(const QName& name, bool useDefaultNs) :
  87. name_(name),
  88. first_attr_(useDefaultNs ? new XmlAttr(QN_XMLNS, name.Namespace()) : NULL),
  89. last_attr_(first_attr_),
  90. first_child_(NULL),
  91. last_child_(NULL),
  92. cdata_(false) {
  93. }
  94. bool XmlElement::IsTextImpl() const {
  95. return false;
  96. }
  97. XmlElement* XmlElement::AsElementImpl() const {
  98. return const_cast<XmlElement *>(this);
  99. }
  100. XmlText* XmlElement::AsTextImpl() const {
  101. return NULL;
  102. }
  103. const std::string XmlElement::BodyText() const {
  104. if (first_child_ && first_child_->IsText() && last_child_ == first_child_) {
  105. return first_child_->AsText()->Text();
  106. }
  107. return std::string();
  108. }
  109. void XmlElement::SetBodyText(const std::string& text) {
  110. if (text.empty()) {
  111. ClearChildren();
  112. } else if (first_child_ == NULL) {
  113. AddText(text);
  114. } else if (first_child_->IsText() && last_child_ == first_child_) {
  115. first_child_->AsText()->SetText(text);
  116. } else {
  117. ClearChildren();
  118. AddText(text);
  119. }
  120. }
  121. const QName XmlElement::FirstElementName() const {
  122. const XmlElement* element = FirstElement();
  123. if (element == NULL)
  124. return QName();
  125. return element->Name();
  126. }
  127. XmlAttr* XmlElement::FirstAttr() {
  128. return first_attr_;
  129. }
  130. const std::string XmlElement::Attr(const StaticQName& name) const {
  131. XmlAttr* attr;
  132. for (attr = first_attr_; attr; attr = attr->next_attr_) {
  133. if (attr->name_ == name)
  134. return attr->value_;
  135. }
  136. return std::string();
  137. }
  138. const std::string XmlElement::Attr(const QName& name) const {
  139. XmlAttr* attr;
  140. for (attr = first_attr_; attr; attr = attr->next_attr_) {
  141. if (attr->name_ == name)
  142. return attr->value_;
  143. }
  144. return std::string();
  145. }
  146. bool XmlElement::HasAttr(const StaticQName& name) const {
  147. XmlAttr* attr;
  148. for (attr = first_attr_; attr; attr = attr->next_attr_) {
  149. if (attr->name_ == name)
  150. return true;
  151. }
  152. return false;
  153. }
  154. bool XmlElement::HasAttr(const QName& name) const {
  155. XmlAttr* attr;
  156. for (attr = first_attr_; attr; attr = attr->next_attr_) {
  157. if (attr->name_ == name)
  158. return true;
  159. }
  160. return false;
  161. }
  162. void XmlElement::SetAttr(const QName& name, const std::string& value) {
  163. XmlAttr* attr;
  164. for (attr = first_attr_; attr; attr = attr->next_attr_) {
  165. if (attr->name_ == name)
  166. break;
  167. }
  168. if (!attr) {
  169. attr = new XmlAttr(name, value);
  170. if (last_attr_)
  171. last_attr_->next_attr_ = attr;
  172. else
  173. first_attr_ = attr;
  174. last_attr_ = attr;
  175. return;
  176. }
  177. attr->value_ = value;
  178. }
  179. void XmlElement::ClearAttr(const QName& name) {
  180. XmlAttr* attr;
  181. XmlAttr* last_attr = NULL;
  182. for (attr = first_attr_; attr; attr = attr->next_attr_) {
  183. if (attr->name_ == name)
  184. break;
  185. last_attr = attr;
  186. }
  187. if (!attr)
  188. return;
  189. if (!last_attr)
  190. first_attr_ = attr->next_attr_;
  191. else
  192. last_attr->next_attr_ = attr->next_attr_;
  193. if (last_attr_ == attr)
  194. last_attr_ = last_attr;
  195. delete attr;
  196. }
  197. XmlChild* XmlElement::FirstChild() {
  198. return first_child_;
  199. }
  200. XmlElement* XmlElement::FirstElement() {
  201. XmlChild* pChild;
  202. for (pChild = first_child_; pChild; pChild = pChild->next_child_) {
  203. if (!pChild->IsText())
  204. return pChild->AsElement();
  205. }
  206. return NULL;
  207. }
  208. XmlElement* XmlElement::NextElement() {
  209. XmlChild* pChild;
  210. for (pChild = next_child_; pChild; pChild = pChild->next_child_) {
  211. if (!pChild->IsText())
  212. return pChild->AsElement();
  213. }
  214. return NULL;
  215. }
  216. XmlElement* XmlElement::FirstWithNamespace(const std::string& ns) {
  217. XmlChild* pChild;
  218. for (pChild = first_child_; pChild; pChild = pChild->next_child_) {
  219. if (!pChild->IsText() && pChild->AsElement()->Name().Namespace() == ns)
  220. return pChild->AsElement();
  221. }
  222. return NULL;
  223. }
  224. XmlElement *
  225. XmlElement::NextWithNamespace(const std::string& ns) {
  226. XmlChild* pChild;
  227. for (pChild = next_child_; pChild; pChild = pChild->next_child_) {
  228. if (!pChild->IsText() && pChild->AsElement()->Name().Namespace() == ns)
  229. return pChild->AsElement();
  230. }
  231. return NULL;
  232. }
  233. XmlElement *
  234. XmlElement::FirstNamed(const QName& name) {
  235. XmlChild* pChild;
  236. for (pChild = first_child_; pChild; pChild = pChild->next_child_) {
  237. if (!pChild->IsText() && pChild->AsElement()->Name() == name)
  238. return pChild->AsElement();
  239. }
  240. return NULL;
  241. }
  242. XmlElement *
  243. XmlElement::FirstNamed(const StaticQName& name) {
  244. XmlChild* pChild;
  245. for (pChild = first_child_; pChild; pChild = pChild->next_child_) {
  246. if (!pChild->IsText() && pChild->AsElement()->Name() == name)
  247. return pChild->AsElement();
  248. }
  249. return NULL;
  250. }
  251. XmlElement *
  252. XmlElement::NextNamed(const QName& name) {
  253. XmlChild* pChild;
  254. for (pChild = next_child_; pChild; pChild = pChild->next_child_) {
  255. if (!pChild->IsText() && pChild->AsElement()->Name() == name)
  256. return pChild->AsElement();
  257. }
  258. return NULL;
  259. }
  260. XmlElement *
  261. XmlElement::NextNamed(const StaticQName& name) {
  262. XmlChild* pChild;
  263. for (pChild = next_child_; pChild; pChild = pChild->next_child_) {
  264. if (!pChild->IsText() && pChild->AsElement()->Name() == name)
  265. return pChild->AsElement();
  266. }
  267. return NULL;
  268. }
  269. XmlElement* XmlElement::FindOrAddNamedChild(const QName& name) {
  270. XmlElement* child = FirstNamed(name);
  271. if (!child) {
  272. child = new XmlElement(name);
  273. AddElement(child);
  274. }
  275. return child;
  276. }
  277. const std::string XmlElement::TextNamed(const QName& name) const {
  278. XmlChild* pChild;
  279. for (pChild = first_child_; pChild; pChild = pChild->next_child_) {
  280. if (!pChild->IsText() && pChild->AsElement()->Name() == name)
  281. return pChild->AsElement()->BodyText();
  282. }
  283. return std::string();
  284. }
  285. void XmlElement::InsertChildAfter(XmlChild* predecessor, XmlChild* next) {
  286. if (predecessor == NULL) {
  287. next->next_child_ = first_child_;
  288. first_child_ = next;
  289. }
  290. else {
  291. next->next_child_ = predecessor->next_child_;
  292. predecessor->next_child_ = next;
  293. }
  294. }
  295. void XmlElement::RemoveChildAfter(XmlChild* predecessor) {
  296. XmlChild* next;
  297. if (predecessor == NULL) {
  298. next = first_child_;
  299. first_child_ = next->next_child_;
  300. }
  301. else {
  302. next = predecessor->next_child_;
  303. predecessor->next_child_ = next->next_child_;
  304. }
  305. if (last_child_ == next)
  306. last_child_ = predecessor;
  307. delete next;
  308. }
  309. void XmlElement::AddAttr(const QName& name, const std::string& value) {
  310. DCHECK(!HasAttr(name));
  311. XmlAttr ** pprev = last_attr_ ? &(last_attr_->next_attr_) : &first_attr_;
  312. last_attr_ = (*pprev = new XmlAttr(name, value));
  313. }
  314. void XmlElement::AddAttr(const QName& name, const std::string& value,
  315. int depth) {
  316. XmlElement* element = this;
  317. while (depth--) {
  318. element = element->last_child_->AsElement();
  319. }
  320. element->AddAttr(name, value);
  321. }
  322. void XmlElement::AddParsedText(const char* cstr, int len) {
  323. if (len == 0)
  324. return;
  325. if (last_child_ && last_child_->IsText()) {
  326. last_child_->AsText()->AddParsedText(cstr, len);
  327. return;
  328. }
  329. XmlChild ** pprev = last_child_ ? &(last_child_->next_child_) : &first_child_;
  330. last_child_ = *pprev = new XmlText(cstr, len);
  331. }
  332. void XmlElement::AddCDATAText(const char* buf, int len) {
  333. cdata_ = true;
  334. AddParsedText(buf, len);
  335. }
  336. void XmlElement::AddText(const std::string& text) {
  337. if (text == STR_EMPTY)
  338. return;
  339. if (last_child_ && last_child_->IsText()) {
  340. last_child_->AsText()->AddText(text);
  341. return;
  342. }
  343. XmlChild ** pprev = last_child_ ? &(last_child_->next_child_) : &first_child_;
  344. last_child_ = *pprev = new XmlText(text);
  345. }
  346. void XmlElement::AddText(const std::string& text, int depth) {
  347. // note: the first syntax is ambigious for msvc 6
  348. // XmlElement* pel(this);
  349. XmlElement* element = this;
  350. while (depth--) {
  351. element = element->last_child_->AsElement();
  352. }
  353. element->AddText(text);
  354. }
  355. void XmlElement::AddElement(XmlElement *child) {
  356. if (child == NULL)
  357. return;
  358. XmlChild ** pprev = last_child_ ? &(last_child_->next_child_) : &first_child_;
  359. *pprev = child;
  360. last_child_ = child;
  361. child->next_child_ = NULL;
  362. }
  363. void XmlElement::AddElement(XmlElement *child, int depth) {
  364. XmlElement* element = this;
  365. while (depth--) {
  366. element = element->last_child_->AsElement();
  367. }
  368. element->AddElement(child);
  369. }
  370. void XmlElement::ClearNamedChildren(const QName& name) {
  371. XmlChild* prev_child = NULL;
  372. XmlChild* next_child;
  373. XmlChild* child;
  374. for (child = FirstChild(); child; child = next_child) {
  375. next_child = child->NextChild();
  376. if (!child->IsText() && child->AsElement()->Name() == name)
  377. {
  378. RemoveChildAfter(prev_child);
  379. continue;
  380. }
  381. prev_child = child;
  382. }
  383. }
  384. void XmlElement::ClearAttributes() {
  385. XmlAttr* attr;
  386. for (attr = first_attr_; attr; ) {
  387. XmlAttr* to_delete = attr;
  388. attr = attr->next_attr_;
  389. delete to_delete;
  390. }
  391. first_attr_ = last_attr_ = NULL;
  392. }
  393. void XmlElement::ClearChildren() {
  394. XmlChild* pchild;
  395. for (pchild = first_child_; pchild; ) {
  396. XmlChild* to_delete = pchild;
  397. pchild = pchild->next_child_;
  398. delete to_delete;
  399. }
  400. first_child_ = last_child_ = NULL;
  401. }
  402. std::string XmlElement::Str() const {
  403. std::stringstream ss;
  404. XmlPrinter::PrintXml(&ss, this);
  405. return ss.str();
  406. }
  407. XmlElement* XmlElement::ForStr(const std::string& str) {
  408. XmlBuilder builder;
  409. XmlParser::ParseXml(&builder, str);
  410. return builder.CreateElement();
  411. }
  412. XmlElement::~XmlElement() {
  413. XmlAttr* attr;
  414. for (attr = first_attr_; attr; ) {
  415. XmlAttr* to_delete = attr;
  416. attr = attr->next_attr_;
  417. delete to_delete;
  418. }
  419. XmlChild* pchild;
  420. for (pchild = first_child_; pchild; ) {
  421. XmlChild* to_delete = pchild;
  422. pchild = pchild->next_child_;
  423. delete to_delete;
  424. }
  425. }
  426. } // namespace jingle_xmpp