1/* 2 * libjingle 3 * Copyright 2004--2005, Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 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. 15 * 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. 26 */ 27 28#include "talk/xmllite/xmlbuilder.h" 29 30#include <vector> 31#include <set> 32#include "talk/base/common.h" 33#include "talk/xmllite/xmlconstants.h" 34#include "talk/xmllite/xmlelement.h" 35 36namespace buzz { 37 38XmlBuilder::XmlBuilder() : 39 pelCurrent_(NULL), 40 pelRoot_(NULL), 41 pvParents_(new std::vector<XmlElement *>()) { 42} 43 44void 45XmlBuilder::Reset() { 46 pelRoot_.reset(); 47 pelCurrent_ = NULL; 48 pvParents_->clear(); 49} 50 51XmlElement * 52XmlBuilder::BuildElement(XmlParseContext * pctx, 53 const char * name, const char ** atts) { 54 QName tagName(pctx->ResolveQName(name, false)); 55 if (tagName.IsEmpty()) 56 return NULL; 57 58 XmlElement * pelNew = new XmlElement(tagName); 59 60 if (!*atts) 61 return pelNew; 62 63 std::set<QName> seenNonlocalAtts; 64 65 while (*atts) { 66 QName attName(pctx->ResolveQName(*atts, true)); 67 if (attName.IsEmpty()) { 68 delete pelNew; 69 return NULL; 70 } 71 72 // verify that namespaced names are unique 73 if (!attName.Namespace().empty()) { 74 if (seenNonlocalAtts.count(attName)) { 75 delete pelNew; 76 return NULL; 77 } 78 seenNonlocalAtts.insert(attName); 79 } 80 81 pelNew->AddAttr(attName, std::string(*(atts + 1))); 82 atts += 2; 83 } 84 85 return pelNew; 86} 87 88void 89XmlBuilder::StartElement(XmlParseContext * pctx, 90 const char * name, const char ** atts) { 91 XmlElement * pelNew = BuildElement(pctx, name, atts); 92 if (pelNew == NULL) { 93 pctx->RaiseError(XML_ERROR_SYNTAX); 94 return; 95 } 96 97 if (!pelCurrent_) { 98 pelCurrent_ = pelNew; 99 pelRoot_.reset(pelNew); 100 pvParents_->push_back(NULL); 101 } else { 102 pelCurrent_->AddElement(pelNew); 103 pvParents_->push_back(pelCurrent_); 104 pelCurrent_ = pelNew; 105 } 106} 107 108void 109XmlBuilder::EndElement(XmlParseContext * pctx, const char * name) { 110 UNUSED(pctx); 111 UNUSED(name); 112 pelCurrent_ = pvParents_->back(); 113 pvParents_->pop_back(); 114} 115 116void 117XmlBuilder::CharacterData(XmlParseContext * pctx, 118 const char * text, int len) { 119 UNUSED(pctx); 120 if (pelCurrent_) { 121 pelCurrent_->AddParsedText(text, len); 122 } 123} 124 125void 126XmlBuilder::Error(XmlParseContext * pctx, XML_Error err) { 127 UNUSED(pctx); 128 UNUSED(err); 129 pelRoot_.reset(NULL); 130 pelCurrent_ = NULL; 131 pvParents_->clear(); 132} 133 134XmlElement * 135XmlBuilder::CreateElement() { 136 return pelRoot_.release(); 137} 138 139XmlElement * 140XmlBuilder::BuiltElement() { 141 return pelRoot_.get(); 142} 143 144XmlBuilder::~XmlBuilder() { 145} 146 147} // namespace buzz 148