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 36 namespace buzz { 37 38 XmlBuilder::XmlBuilder() : 39 pelCurrent_(NULL), 40 pelRoot_(), 41 pvParents_(new std::vector<XmlElement *>()) { 42 } 43 44 void 45 XmlBuilder::Reset() { 46 pelRoot_.reset(); 47 pelCurrent_ = NULL; 48 pvParents_->clear(); 49 } 50 51 XmlElement * 52 XmlBuilder::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 88 void 89 XmlBuilder::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 108 void 109 XmlBuilder::EndElement(XmlParseContext * pctx, const char * name) { 110 UNUSED(pctx); 111 UNUSED(name); 112 pelCurrent_ = pvParents_->back(); 113 pvParents_->pop_back(); 114 } 115 116 void 117 XmlBuilder::CharacterData(XmlParseContext * pctx, 118 const char * text, int len) { 119 UNUSED(pctx); 120 if (pelCurrent_) { 121 pelCurrent_->AddParsedText(text, len); 122 } 123 } 124 125 void 126 XmlBuilder::Error(XmlParseContext * pctx, XML_Error err) { 127 UNUSED(pctx); 128 UNUSED(err); 129 pelRoot_.reset(NULL); 130 pelCurrent_ = NULL; 131 pvParents_->clear(); 132 } 133 134 XmlElement * 135 XmlBuilder::CreateElement() { 136 return pelRoot_.release(); 137 } 138 139 XmlElement * 140 XmlBuilder::BuiltElement() { 141 return pelRoot_.get(); 142 } 143 144 XmlBuilder::~XmlBuilder() { 145 } 146 147 } // namespace buzz 148