3
* Copyright 2004--2005, Google Inc.
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions are met:
8
* 1. Redistributions of source code must retain the above copyright notice,
9
* this list of conditions and the following disclaimer.
10
* 2. Redistributions in binary form must reproduce the above copyright notice,
11
* this list of conditions and the following disclaimer in the documentation
12
* and/or other materials provided with the distribution.
13
* 3. The name of the author may not be used to endorse or promote products
14
* derived from this software without specific prior written permission.
16
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
#include "talk/xmllite/xmlelement.h"
35
#include "talk/base/common.h"
36
#include "talk/xmllite/qname.h"
37
#include "talk/xmllite/xmlparser.h"
38
#include "talk/xmllite/xmlbuilder.h"
39
#include "talk/xmllite/xmlprinter.h"
40
#include "talk/xmllite/xmlconstants.h"
44
XmlChild::~XmlChild() {
47
bool XmlText::IsTextImpl() const {
51
XmlElement* XmlText::AsElementImpl() const {
55
XmlText* XmlText::AsTextImpl() const {
56
return const_cast<XmlText *>(this);
59
void XmlText::SetText(const std::string& text) {
63
void XmlText::AddParsedText(const char* buf, int len) {
64
text_.append(buf, len);
67
void XmlText::AddText(const std::string& text) {
74
XmlElement::XmlElement(const QName& name) :
83
XmlElement::XmlElement(const XmlElement& elt) :
94
XmlAttr ** plast_attr = &first_attr_;
95
XmlAttr* newAttr = NULL;
96
for (attr = elt.first_attr_; attr; attr = attr->NextAttr()) {
97
newAttr = new XmlAttr(*attr);
98
*plast_attr = newAttr;
99
plast_attr = &(newAttr->next_attr_);
101
last_attr_ = newAttr;
105
XmlChild ** ppLast = &first_child_;
106
XmlChild* newChild = NULL;
108
for (pChild = elt.first_child_; pChild; pChild = pChild->NextChild()) {
109
if (pChild->IsText()) {
110
newChild = new XmlText(*(pChild->AsText()));
112
newChild = new XmlElement(*(pChild->AsElement()));
115
ppLast = &(newChild->next_child_);
117
last_child_ = newChild;
122
XmlElement::XmlElement(const QName& name, bool useDefaultNs) :
124
first_attr_(useDefaultNs ? new XmlAttr(QN_XMLNS, name.Namespace()) : NULL),
125
last_attr_(first_attr_),
131
bool XmlElement::IsTextImpl() const {
135
XmlElement* XmlElement::AsElementImpl() const {
136
return const_cast<XmlElement *>(this);
139
XmlText* XmlElement::AsTextImpl() const {
143
const std::string XmlElement::BodyText() const {
144
if (first_child_ && first_child_->IsText() && last_child_ == first_child_) {
145
return first_child_->AsText()->Text();
148
return std::string();
151
void XmlElement::SetBodyText(const std::string& text) {
154
} else if (first_child_ == NULL) {
156
} else if (first_child_->IsText() && last_child_ == first_child_) {
157
first_child_->AsText()->SetText(text);
164
const QName XmlElement::FirstElementName() const {
165
const XmlElement* element = FirstElement();
168
return element->Name();
171
XmlAttr* XmlElement::FirstAttr() {
175
const std::string XmlElement::Attr(const StaticQName& name) const {
177
for (attr = first_attr_; attr; attr = attr->next_attr_) {
178
if (attr->name_ == name)
181
return std::string();
184
const std::string XmlElement::Attr(const QName& name) const {
186
for (attr = first_attr_; attr; attr = attr->next_attr_) {
187
if (attr->name_ == name)
190
return std::string();
193
bool XmlElement::HasAttr(const StaticQName& name) const {
195
for (attr = first_attr_; attr; attr = attr->next_attr_) {
196
if (attr->name_ == name)
202
bool XmlElement::HasAttr(const QName& name) const {
204
for (attr = first_attr_; attr; attr = attr->next_attr_) {
205
if (attr->name_ == name)
211
void XmlElement::SetAttr(const QName& name, const std::string& value) {
213
for (attr = first_attr_; attr; attr = attr->next_attr_) {
214
if (attr->name_ == name)
218
attr = new XmlAttr(name, value);
220
last_attr_->next_attr_ = attr;
226
attr->value_ = value;
229
void XmlElement::ClearAttr(const QName& name) {
231
XmlAttr* last_attr = NULL;
232
for (attr = first_attr_; attr; attr = attr->next_attr_) {
233
if (attr->name_ == name)
240
first_attr_ = attr->next_attr_;
242
last_attr->next_attr_ = attr->next_attr_;
243
if (last_attr_ == attr)
244
last_attr_ = last_attr;
248
XmlChild* XmlElement::FirstChild() {
252
XmlElement* XmlElement::FirstElement() {
254
for (pChild = first_child_; pChild; pChild = pChild->next_child_) {
255
if (!pChild->IsText())
256
return pChild->AsElement();
261
XmlElement* XmlElement::NextElement() {
263
for (pChild = next_child_; pChild; pChild = pChild->next_child_) {
264
if (!pChild->IsText())
265
return pChild->AsElement();
270
XmlElement* XmlElement::FirstWithNamespace(const std::string& ns) {
272
for (pChild = first_child_; pChild; pChild = pChild->next_child_) {
273
if (!pChild->IsText() && pChild->AsElement()->Name().Namespace() == ns)
274
return pChild->AsElement();
280
XmlElement::NextWithNamespace(const std::string& ns) {
282
for (pChild = next_child_; pChild; pChild = pChild->next_child_) {
283
if (!pChild->IsText() && pChild->AsElement()->Name().Namespace() == ns)
284
return pChild->AsElement();
290
XmlElement::FirstNamed(const QName& name) {
292
for (pChild = first_child_; pChild; pChild = pChild->next_child_) {
293
if (!pChild->IsText() && pChild->AsElement()->Name() == name)
294
return pChild->AsElement();
300
XmlElement::FirstNamed(const StaticQName& name) {
302
for (pChild = first_child_; pChild; pChild = pChild->next_child_) {
303
if (!pChild->IsText() && pChild->AsElement()->Name() == name)
304
return pChild->AsElement();
310
XmlElement::NextNamed(const QName& name) {
312
for (pChild = next_child_; pChild; pChild = pChild->next_child_) {
313
if (!pChild->IsText() && pChild->AsElement()->Name() == name)
314
return pChild->AsElement();
320
XmlElement::NextNamed(const StaticQName& name) {
322
for (pChild = next_child_; pChild; pChild = pChild->next_child_) {
323
if (!pChild->IsText() && pChild->AsElement()->Name() == name)
324
return pChild->AsElement();
329
XmlElement* XmlElement::FindOrAddNamedChild(const QName& name) {
330
XmlElement* child = FirstNamed(name);
332
child = new XmlElement(name);
339
const std::string XmlElement::TextNamed(const QName& name) const {
341
for (pChild = first_child_; pChild; pChild = pChild->next_child_) {
342
if (!pChild->IsText() && pChild->AsElement()->Name() == name)
343
return pChild->AsElement()->BodyText();
345
return std::string();
348
void XmlElement::InsertChildAfter(XmlChild* predecessor, XmlChild* next) {
349
if (predecessor == NULL) {
350
next->next_child_ = first_child_;
354
next->next_child_ = predecessor->next_child_;
355
predecessor->next_child_ = next;
359
void XmlElement::RemoveChildAfter(XmlChild* predecessor) {
362
if (predecessor == NULL) {
364
first_child_ = next->next_child_;
367
next = predecessor->next_child_;
368
predecessor->next_child_ = next->next_child_;
371
if (last_child_ == next)
372
last_child_ = predecessor;
377
void XmlElement::AddAttr(const QName& name, const std::string& value) {
378
ASSERT(!HasAttr(name));
380
XmlAttr ** pprev = last_attr_ ? &(last_attr_->next_attr_) : &first_attr_;
381
last_attr_ = (*pprev = new XmlAttr(name, value));
384
void XmlElement::AddAttr(const QName& name, const std::string& value,
386
XmlElement* element = this;
388
element = element->last_child_->AsElement();
390
element->AddAttr(name, value);
393
void XmlElement::AddParsedText(const char* cstr, int len) {
397
if (last_child_ && last_child_->IsText()) {
398
last_child_->AsText()->AddParsedText(cstr, len);
401
XmlChild ** pprev = last_child_ ? &(last_child_->next_child_) : &first_child_;
402
last_child_ = *pprev = new XmlText(cstr, len);
405
void XmlElement::AddCDATAText(const char* buf, int len) {
407
AddParsedText(buf, len);
410
void XmlElement::AddText(const std::string& text) {
411
if (text == STR_EMPTY)
414
if (last_child_ && last_child_->IsText()) {
415
last_child_->AsText()->AddText(text);
418
XmlChild ** pprev = last_child_ ? &(last_child_->next_child_) : &first_child_;
419
last_child_ = *pprev = new XmlText(text);
422
void XmlElement::AddText(const std::string& text, int depth) {
423
// note: the first syntax is ambigious for msvc 6
424
// XmlElement* pel(this);
425
XmlElement* element = this;
427
element = element->last_child_->AsElement();
429
element->AddText(text);
432
void XmlElement::AddElement(XmlElement *child) {
436
XmlChild ** pprev = last_child_ ? &(last_child_->next_child_) : &first_child_;
439
child->next_child_ = NULL;
442
void XmlElement::AddElement(XmlElement *child, int depth) {
443
XmlElement* element = this;
445
element = element->last_child_->AsElement();
447
element->AddElement(child);
450
void XmlElement::ClearNamedChildren(const QName& name) {
451
XmlChild* prev_child = NULL;
452
XmlChild* next_child;
454
for (child = FirstChild(); child; child = next_child) {
455
next_child = child->NextChild();
456
if (!child->IsText() && child->AsElement()->Name() == name)
458
RemoveChildAfter(prev_child);
465
void XmlElement::ClearAttributes() {
467
for (attr = first_attr_; attr; ) {
468
XmlAttr* to_delete = attr;
469
attr = attr->next_attr_;
472
first_attr_ = last_attr_ = NULL;
475
void XmlElement::ClearChildren() {
477
for (pchild = first_child_; pchild; ) {
478
XmlChild* to_delete = pchild;
479
pchild = pchild->next_child_;
482
first_child_ = last_child_ = NULL;
485
std::string XmlElement::Str() const {
486
std::stringstream ss;
487
XmlPrinter::PrintXml(&ss, this);
491
XmlElement* XmlElement::ForStr(const std::string& str) {
493
XmlParser::ParseXml(&builder, str);
494
return builder.CreateElement();
497
XmlElement::~XmlElement() {
499
for (attr = first_attr_; attr; ) {
500
XmlAttr* to_delete = attr;
501
attr = attr->next_attr_;
506
for (pchild = first_child_; pchild; ) {
507
XmlChild* to_delete = pchild;
508
pchild = pchild->next_child_;