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