Removes xmllite from talk/xmllite since webrtc/xmllite is used instead.
BUG=3379 R=marpan@google.com Review URL: https://webrtc-codereview.appspot.com/23039004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@7436 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
8bee130fa0
commit
1e6a5dd14e
@ -1,95 +0,0 @@
|
||||
/*
|
||||
* libjingle
|
||||
* Copyright 2004--2005, Google Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "talk/xmllite/qname.h"
|
||||
|
||||
namespace buzz {
|
||||
|
||||
QName::QName() {
|
||||
}
|
||||
|
||||
QName::QName(const QName& qname)
|
||||
: namespace_(qname.namespace_),
|
||||
local_part_(qname.local_part_) {
|
||||
}
|
||||
|
||||
QName::QName(const StaticQName& const_value)
|
||||
: namespace_(const_value.ns),
|
||||
local_part_(const_value.local) {
|
||||
}
|
||||
|
||||
QName::QName(const std::string& ns, const std::string& local)
|
||||
: namespace_(ns),
|
||||
local_part_(local) {
|
||||
}
|
||||
|
||||
QName::QName(const std::string& merged_or_local) {
|
||||
size_t i = merged_or_local.rfind(':');
|
||||
if (i == std::string::npos) {
|
||||
local_part_ = merged_or_local;
|
||||
} else {
|
||||
namespace_ = merged_or_local.substr(0, i);
|
||||
local_part_ = merged_or_local.substr(i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
QName::~QName() {
|
||||
}
|
||||
|
||||
std::string QName::Merged() const {
|
||||
if (namespace_[0] == '\0')
|
||||
return local_part_;
|
||||
|
||||
std::string result;
|
||||
result.reserve(namespace_.length() + 1 + local_part_.length());
|
||||
result += namespace_;
|
||||
result += ':';
|
||||
result += local_part_;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool QName::IsEmpty() const {
|
||||
return namespace_.empty() && local_part_.empty();
|
||||
}
|
||||
|
||||
int QName::Compare(const StaticQName& other) const {
|
||||
int result = local_part_.compare(other.local);
|
||||
if (result != 0)
|
||||
return result;
|
||||
|
||||
return namespace_.compare(other.ns);
|
||||
}
|
||||
|
||||
int QName::Compare(const QName& other) const {
|
||||
int result = local_part_.compare(other.local_part_);
|
||||
if (result != 0)
|
||||
return result;
|
||||
|
||||
return namespace_.compare(other.namespace_);
|
||||
}
|
||||
|
||||
} // namespace buzz
|
@ -1,100 +0,0 @@
|
||||
/*
|
||||
* libjingle
|
||||
* Copyright 2004--2005, Google Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef TALK_XMLLITE_QNAME_H_
|
||||
#define TALK_XMLLITE_QNAME_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace buzz {
|
||||
|
||||
class QName;
|
||||
|
||||
// StaticQName is used to represend constant quailified names. They
|
||||
// can be initialized statically and don't need intializers code, e.g.
|
||||
// const StaticQName QN_FOO = { "foo_namespace", "foo" };
|
||||
//
|
||||
// Beside this use case, QName should be used everywhere
|
||||
// else. StaticQName instances are implicitly converted to QName
|
||||
// objects.
|
||||
struct StaticQName {
|
||||
const char* const ns;
|
||||
const char* const local;
|
||||
|
||||
bool operator==(const QName& other) const;
|
||||
bool operator!=(const QName& other) const;
|
||||
};
|
||||
|
||||
class QName {
|
||||
public:
|
||||
QName();
|
||||
QName(const QName& qname);
|
||||
QName(const StaticQName& const_value);
|
||||
QName(const std::string& ns, const std::string& local);
|
||||
explicit QName(const std::string& merged_or_local);
|
||||
~QName();
|
||||
|
||||
const std::string& Namespace() const { return namespace_; }
|
||||
const std::string& LocalPart() const { return local_part_; }
|
||||
std::string Merged() const;
|
||||
bool IsEmpty() const;
|
||||
|
||||
int Compare(const StaticQName& other) const;
|
||||
int Compare(const QName& other) const;
|
||||
|
||||
bool operator==(const StaticQName& other) const {
|
||||
return Compare(other) == 0;
|
||||
}
|
||||
bool operator==(const QName& other) const {
|
||||
return Compare(other) == 0;
|
||||
}
|
||||
bool operator!=(const StaticQName& other) const {
|
||||
return Compare(other) != 0;
|
||||
}
|
||||
bool operator!=(const QName& other) const {
|
||||
return Compare(other) != 0;
|
||||
}
|
||||
bool operator<(const QName& other) const {
|
||||
return Compare(other) < 0;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string namespace_;
|
||||
std::string local_part_;
|
||||
};
|
||||
|
||||
inline bool StaticQName::operator==(const QName& other) const {
|
||||
return other.Compare(*this) == 0;
|
||||
}
|
||||
|
||||
inline bool StaticQName::operator!=(const QName& other) const {
|
||||
return other.Compare(*this) != 0;
|
||||
}
|
||||
|
||||
} // namespace buzz
|
||||
|
||||
#endif // TALK_XMLLITE_QNAME_H_
|
@ -1,131 +0,0 @@
|
||||
/*
|
||||
* libjingle
|
||||
* Copyright 2004, Google Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include "talk/xmllite/qname.h"
|
||||
#include "webrtc/base/gunit.h"
|
||||
|
||||
using buzz::StaticQName;
|
||||
using buzz::QName;
|
||||
|
||||
TEST(QNameTest, TestTrivial) {
|
||||
QName name("test");
|
||||
EXPECT_EQ(name.LocalPart(), "test");
|
||||
EXPECT_EQ(name.Namespace(), "");
|
||||
}
|
||||
|
||||
TEST(QNameTest, TestSplit) {
|
||||
QName name("a:test");
|
||||
EXPECT_EQ(name.LocalPart(), "test");
|
||||
EXPECT_EQ(name.Namespace(), "a");
|
||||
QName name2("a-very:long:namespace:test-this");
|
||||
EXPECT_EQ(name2.LocalPart(), "test-this");
|
||||
EXPECT_EQ(name2.Namespace(), "a-very:long:namespace");
|
||||
}
|
||||
|
||||
TEST(QNameTest, TestMerge) {
|
||||
QName name("a", "test");
|
||||
EXPECT_EQ(name.LocalPart(), "test");
|
||||
EXPECT_EQ(name.Namespace(), "a");
|
||||
EXPECT_EQ(name.Merged(), "a:test");
|
||||
QName name2("a-very:long:namespace", "test-this");
|
||||
EXPECT_EQ(name2.LocalPart(), "test-this");
|
||||
EXPECT_EQ(name2.Namespace(), "a-very:long:namespace");
|
||||
EXPECT_EQ(name2.Merged(), "a-very:long:namespace:test-this");
|
||||
}
|
||||
|
||||
TEST(QNameTest, TestAssignment) {
|
||||
QName name("a", "test");
|
||||
// copy constructor
|
||||
QName namecopy(name);
|
||||
EXPECT_EQ(namecopy.LocalPart(), "test");
|
||||
EXPECT_EQ(namecopy.Namespace(), "a");
|
||||
QName nameassigned("");
|
||||
nameassigned = name;
|
||||
EXPECT_EQ(nameassigned.LocalPart(), "test");
|
||||
EXPECT_EQ(nameassigned.Namespace(), "a");
|
||||
}
|
||||
|
||||
TEST(QNameTest, TestConstAssignment) {
|
||||
StaticQName name = { "a", "test" };
|
||||
QName namecopy(name);
|
||||
EXPECT_EQ(namecopy.LocalPart(), "test");
|
||||
EXPECT_EQ(namecopy.Namespace(), "a");
|
||||
QName nameassigned("");
|
||||
nameassigned = name;
|
||||
EXPECT_EQ(nameassigned.LocalPart(), "test");
|
||||
EXPECT_EQ(nameassigned.Namespace(), "a");
|
||||
}
|
||||
|
||||
TEST(QNameTest, TestEquality) {
|
||||
QName name("a-very:long:namespace:test-this");
|
||||
QName name2("a-very:long:namespace", "test-this");
|
||||
QName name3("a-very:long:namespaxe", "test-this");
|
||||
EXPECT_TRUE(name == name2);
|
||||
EXPECT_FALSE(name == name3);
|
||||
}
|
||||
|
||||
TEST(QNameTest, TestCompare) {
|
||||
QName name("a");
|
||||
QName name2("nsa", "a");
|
||||
QName name3("nsa", "b");
|
||||
QName name4("nsb", "b");
|
||||
|
||||
EXPECT_TRUE(name < name2);
|
||||
EXPECT_FALSE(name2 < name);
|
||||
|
||||
EXPECT_FALSE(name2 < name2);
|
||||
|
||||
EXPECT_TRUE(name2 < name3);
|
||||
EXPECT_FALSE(name3 < name2);
|
||||
|
||||
EXPECT_TRUE(name3 < name4);
|
||||
EXPECT_FALSE(name4 < name3);
|
||||
}
|
||||
|
||||
TEST(QNameTest, TestStaticQName) {
|
||||
const StaticQName const_name1 = { "namespace", "local-name1" };
|
||||
const StaticQName const_name2 = { "namespace", "local-name2" };
|
||||
const QName name("namespace", "local-name1");
|
||||
const QName name1 = const_name1;
|
||||
const QName name2 = const_name2;
|
||||
|
||||
EXPECT_TRUE(name == const_name1);
|
||||
EXPECT_TRUE(const_name1 == name);
|
||||
EXPECT_FALSE(name != const_name1);
|
||||
EXPECT_FALSE(const_name1 != name);
|
||||
|
||||
EXPECT_TRUE(name == name1);
|
||||
EXPECT_TRUE(name1 == name);
|
||||
EXPECT_FALSE(name != name1);
|
||||
EXPECT_FALSE(name1 != name);
|
||||
|
||||
EXPECT_FALSE(name == name2);
|
||||
EXPECT_FALSE(name2 == name);
|
||||
EXPECT_TRUE(name != name2);
|
||||
EXPECT_TRUE(name2 != name);
|
||||
}
|
@ -1,147 +0,0 @@
|
||||
/*
|
||||
* libjingle
|
||||
* Copyright 2004--2005, Google Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "talk/xmllite/xmlbuilder.h"
|
||||
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include "talk/xmllite/xmlconstants.h"
|
||||
#include "talk/xmllite/xmlelement.h"
|
||||
#include "webrtc/base/common.h"
|
||||
|
||||
namespace buzz {
|
||||
|
||||
XmlBuilder::XmlBuilder() :
|
||||
pelCurrent_(NULL),
|
||||
pelRoot_(),
|
||||
pvParents_(new std::vector<XmlElement *>()) {
|
||||
}
|
||||
|
||||
void
|
||||
XmlBuilder::Reset() {
|
||||
pelRoot_.reset();
|
||||
pelCurrent_ = NULL;
|
||||
pvParents_->clear();
|
||||
}
|
||||
|
||||
XmlElement *
|
||||
XmlBuilder::BuildElement(XmlParseContext * pctx,
|
||||
const char * name, const char ** atts) {
|
||||
QName tagName(pctx->ResolveQName(name, false));
|
||||
if (tagName.IsEmpty())
|
||||
return NULL;
|
||||
|
||||
XmlElement * pelNew = new XmlElement(tagName);
|
||||
|
||||
if (!*atts)
|
||||
return pelNew;
|
||||
|
||||
std::set<QName> seenNonlocalAtts;
|
||||
|
||||
while (*atts) {
|
||||
QName attName(pctx->ResolveQName(*atts, true));
|
||||
if (attName.IsEmpty()) {
|
||||
delete pelNew;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// verify that namespaced names are unique
|
||||
if (!attName.Namespace().empty()) {
|
||||
if (seenNonlocalAtts.count(attName)) {
|
||||
delete pelNew;
|
||||
return NULL;
|
||||
}
|
||||
seenNonlocalAtts.insert(attName);
|
||||
}
|
||||
|
||||
pelNew->AddAttr(attName, std::string(*(atts + 1)));
|
||||
atts += 2;
|
||||
}
|
||||
|
||||
return pelNew;
|
||||
}
|
||||
|
||||
void
|
||||
XmlBuilder::StartElement(XmlParseContext * pctx,
|
||||
const char * name, const char ** atts) {
|
||||
XmlElement * pelNew = BuildElement(pctx, name, atts);
|
||||
if (pelNew == NULL) {
|
||||
pctx->RaiseError(XML_ERROR_SYNTAX);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pelCurrent_) {
|
||||
pelCurrent_ = pelNew;
|
||||
pelRoot_.reset(pelNew);
|
||||
pvParents_->push_back(NULL);
|
||||
} else {
|
||||
pelCurrent_->AddElement(pelNew);
|
||||
pvParents_->push_back(pelCurrent_);
|
||||
pelCurrent_ = pelNew;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
XmlBuilder::EndElement(XmlParseContext * pctx, const char * name) {
|
||||
RTC_UNUSED(pctx);
|
||||
RTC_UNUSED(name);
|
||||
pelCurrent_ = pvParents_->back();
|
||||
pvParents_->pop_back();
|
||||
}
|
||||
|
||||
void
|
||||
XmlBuilder::CharacterData(XmlParseContext * pctx,
|
||||
const char * text, int len) {
|
||||
RTC_UNUSED(pctx);
|
||||
if (pelCurrent_) {
|
||||
pelCurrent_->AddParsedText(text, len);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
XmlBuilder::Error(XmlParseContext * pctx, XML_Error err) {
|
||||
RTC_UNUSED(pctx);
|
||||
RTC_UNUSED(err);
|
||||
pelRoot_.reset(NULL);
|
||||
pelCurrent_ = NULL;
|
||||
pvParents_->clear();
|
||||
}
|
||||
|
||||
XmlElement *
|
||||
XmlBuilder::CreateElement() {
|
||||
return pelRoot_.release();
|
||||
}
|
||||
|
||||
XmlElement *
|
||||
XmlBuilder::BuiltElement() {
|
||||
return pelRoot_.get();
|
||||
}
|
||||
|
||||
XmlBuilder::~XmlBuilder() {
|
||||
}
|
||||
|
||||
} // namespace buzz
|
@ -1,78 +0,0 @@
|
||||
/*
|
||||
* libjingle
|
||||
* Copyright 2004--2005, Google Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _xmlbuilder_h_
|
||||
#define _xmlbuilder_h_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "talk/xmllite/xmlparser.h"
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
|
||||
#ifdef EXPAT_RELATIVE_PATH
|
||||
#include "expat.h"
|
||||
#else
|
||||
#include "third_party/expat/v2_0_1/Source/lib/expat.h"
|
||||
#endif // EXPAT_RELATIVE_PATH
|
||||
|
||||
namespace buzz {
|
||||
|
||||
class XmlElement;
|
||||
class XmlParseContext;
|
||||
|
||||
|
||||
class XmlBuilder : public XmlParseHandler {
|
||||
public:
|
||||
XmlBuilder();
|
||||
|
||||
static XmlElement * BuildElement(XmlParseContext * pctx,
|
||||
const char * name, const char ** atts);
|
||||
virtual void StartElement(XmlParseContext * pctx,
|
||||
const char * name, const char ** atts);
|
||||
virtual void EndElement(XmlParseContext * pctx, const char * name);
|
||||
virtual void CharacterData(XmlParseContext * pctx,
|
||||
const char * text, int len);
|
||||
virtual void Error(XmlParseContext * pctx, XML_Error);
|
||||
virtual ~XmlBuilder();
|
||||
|
||||
void Reset();
|
||||
|
||||
// Take ownership of the built element; second call returns NULL
|
||||
XmlElement * CreateElement();
|
||||
|
||||
// Peek at the built element without taking ownership
|
||||
XmlElement * BuiltElement();
|
||||
|
||||
private:
|
||||
XmlElement * pelCurrent_;
|
||||
rtc::scoped_ptr<XmlElement> pelRoot_;
|
||||
rtc::scoped_ptr<std::vector<XmlElement*> > pvParents_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -1,194 +0,0 @@
|
||||
/*
|
||||
* libjingle
|
||||
* Copyright 2004, Google Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include "talk/xmllite/xmlbuilder.h"
|
||||
#include "talk/xmllite/xmlelement.h"
|
||||
#include "talk/xmllite/xmlparser.h"
|
||||
#include "webrtc/base/common.h"
|
||||
#include "webrtc/base/gunit.h"
|
||||
|
||||
using buzz::XmlBuilder;
|
||||
using buzz::XmlElement;
|
||||
using buzz::XmlParser;
|
||||
|
||||
TEST(XmlBuilderTest, TestTrivial) {
|
||||
XmlBuilder builder;
|
||||
XmlParser::ParseXml(&builder, "<testing/>");
|
||||
EXPECT_EQ("<testing/>", builder.BuiltElement()->Str());
|
||||
}
|
||||
|
||||
TEST(XmlBuilderTest, TestAttributes1) {
|
||||
XmlBuilder builder;
|
||||
XmlParser::ParseXml(&builder, "<testing a='b'/>");
|
||||
EXPECT_EQ("<testing a=\"b\"/>", builder.BuiltElement()->Str());
|
||||
}
|
||||
|
||||
TEST(XmlBuilderTest, TestAttributes2) {
|
||||
XmlBuilder builder;
|
||||
XmlParser::ParseXml(&builder, "<testing e='' long='some text'/>");
|
||||
EXPECT_EQ("<testing e=\"\" long=\"some text\"/>",
|
||||
builder.BuiltElement()->Str());
|
||||
}
|
||||
|
||||
TEST(XmlBuilderTest, TestNesting1) {
|
||||
XmlBuilder builder;
|
||||
XmlParser::ParseXml(&builder,
|
||||
"<top><first/><second><third></third></second></top>");
|
||||
EXPECT_EQ("<top><first/><second><third/></second></top>",
|
||||
builder.BuiltElement()->Str());
|
||||
}
|
||||
|
||||
TEST(XmlBuilderTest, TestNesting2) {
|
||||
XmlBuilder builder;
|
||||
XmlParser::ParseXml(&builder,
|
||||
"<top><fifth><deeper><and><deeper/></and><sibling><leaf/>"
|
||||
"</sibling></deeper></fifth><first/><second><third></third>"
|
||||
"</second></top>");
|
||||
EXPECT_EQ("<top><fifth><deeper><and><deeper/></and><sibling><leaf/>"
|
||||
"</sibling></deeper></fifth><first/><second><third/>"
|
||||
"</second></top>", builder.BuiltElement()->Str());
|
||||
}
|
||||
|
||||
TEST(XmlBuilderTest, TestQuoting1) {
|
||||
XmlBuilder builder;
|
||||
XmlParser::ParseXml(&builder, "<testing a='>'/>");
|
||||
EXPECT_EQ("<testing a=\">\"/>", builder.BuiltElement()->Str());
|
||||
}
|
||||
|
||||
TEST(XmlBuilderTest, TestQuoting2) {
|
||||
XmlBuilder builder;
|
||||
XmlParser::ParseXml(&builder, "<testing a='<>&"'/>");
|
||||
EXPECT_EQ("<testing a=\"<>&"\"/>",
|
||||
builder.BuiltElement()->Str());
|
||||
}
|
||||
|
||||
TEST(XmlBuilderTest, TestQuoting3) {
|
||||
XmlBuilder builder;
|
||||
XmlParser::ParseXml(&builder, "<testing a='so "important"'/>");
|
||||
EXPECT_EQ("<testing a=\"so "important"\"/>",
|
||||
builder.BuiltElement()->Str());
|
||||
}
|
||||
|
||||
TEST(XmlBuilderTest, TestQuoting4) {
|
||||
XmlBuilder builder;
|
||||
XmlParser::ParseXml(&builder, "<testing a='"important", yes'/>");
|
||||
EXPECT_EQ("<testing a=\""important", yes\"/>",
|
||||
builder.BuiltElement()->Str());
|
||||
}
|
||||
|
||||
TEST(XmlBuilderTest, TestQuoting5) {
|
||||
XmlBuilder builder;
|
||||
XmlParser::ParseXml(&builder,
|
||||
"<testing a='<what is "important">'/>");
|
||||
EXPECT_EQ("<testing a=\"<what is "important">\"/>",
|
||||
builder.BuiltElement()->Str());
|
||||
}
|
||||
|
||||
TEST(XmlBuilderTest, TestText1) {
|
||||
XmlBuilder builder;
|
||||
XmlParser::ParseXml(&builder, "<testing>></testing>");
|
||||
EXPECT_EQ("<testing>></testing>", builder.BuiltElement()->Str());
|
||||
}
|
||||
|
||||
TEST(XmlBuilderTest, TestText2) {
|
||||
XmlBuilder builder;
|
||||
XmlParser::ParseXml(&builder, "<testing><>&"</testing>");
|
||||
EXPECT_EQ("<testing><>&\"</testing>",
|
||||
builder.BuiltElement()->Str());
|
||||
}
|
||||
|
||||
TEST(XmlBuilderTest, TestText3) {
|
||||
XmlBuilder builder;
|
||||
XmlParser::ParseXml(&builder, "<testing>so <important></testing>");
|
||||
EXPECT_EQ("<testing>so <important></testing>",
|
||||
builder.BuiltElement()->Str());
|
||||
}
|
||||
|
||||
TEST(XmlBuilderTest, TestText4) {
|
||||
XmlBuilder builder;
|
||||
XmlParser::ParseXml(&builder, "<testing><important>, yes</testing>");
|
||||
EXPECT_EQ("<testing><important>, yes</testing>",
|
||||
builder.BuiltElement()->Str());
|
||||
}
|
||||
|
||||
TEST(XmlBuilderTest, TestText5) {
|
||||
XmlBuilder builder;
|
||||
XmlParser::ParseXml(&builder,
|
||||
"<testing>importance &<important>&</testing>");
|
||||
EXPECT_EQ("<testing>importance &<important>&</testing>",
|
||||
builder.BuiltElement()->Str());
|
||||
}
|
||||
|
||||
TEST(XmlBuilderTest, TestNamespace1) {
|
||||
XmlBuilder builder;
|
||||
XmlParser::ParseXml(&builder, "<testing xmlns='foo'/>");
|
||||
EXPECT_EQ("<testing xmlns=\"foo\"/>", builder.BuiltElement()->Str());
|
||||
}
|
||||
|
||||
TEST(XmlBuilderTest, TestNamespace2) {
|
||||
XmlBuilder builder;
|
||||
XmlParser::ParseXml(&builder, "<testing xmlns:a='foo' a:b='c'/>");
|
||||
EXPECT_EQ("<testing xmlns:a=\"foo\" a:b=\"c\"/>",
|
||||
builder.BuiltElement()->Str());
|
||||
}
|
||||
|
||||
TEST(XmlBuilderTest, TestNamespace3) {
|
||||
XmlBuilder builder;
|
||||
XmlParser::ParseXml(&builder, "<testing xmlns:a=''/>");
|
||||
EXPECT_TRUE(NULL == builder.BuiltElement());
|
||||
}
|
||||
|
||||
TEST(XmlBuilderTest, TestNamespace4) {
|
||||
XmlBuilder builder;
|
||||
XmlParser::ParseXml(&builder, "<testing a:b='c'/>");
|
||||
EXPECT_TRUE(NULL == builder.BuiltElement());
|
||||
}
|
||||
|
||||
TEST(XmlBuilderTest, TestAttrCollision1) {
|
||||
XmlBuilder builder;
|
||||
XmlParser::ParseXml(&builder, "<testing a='first' a='second'/>");
|
||||
EXPECT_TRUE(NULL == builder.BuiltElement());
|
||||
}
|
||||
|
||||
TEST(XmlBuilderTest, TestAttrCollision2) {
|
||||
XmlBuilder builder;
|
||||
XmlParser::ParseXml(&builder,
|
||||
"<testing xmlns:a='foo' xmlns:b='foo' a:x='c' b:x='d'/>");
|
||||
EXPECT_TRUE(NULL == builder.BuiltElement());
|
||||
}
|
||||
|
||||
TEST(XmlBuilderTest, TestAttrCollision3) {
|
||||
XmlBuilder builder;
|
||||
XmlParser::ParseXml(&builder,
|
||||
"<testing xmlns:a='foo'><nested xmlns:b='foo' a:x='c' b:x='d'/>"
|
||||
"</testing>");
|
||||
EXPECT_TRUE(NULL == builder.BuiltElement());
|
||||
}
|
||||
|
@ -1,42 +0,0 @@
|
||||
/*
|
||||
* libjingle
|
||||
* Copyright 2004--2005, Google Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "talk/xmllite/xmlconstants.h"
|
||||
|
||||
namespace buzz {
|
||||
|
||||
const char STR_EMPTY[] = "";
|
||||
const char NS_XML[] = "http://www.w3.org/XML/1998/namespace";
|
||||
const char NS_XMLNS[] = "http://www.w3.org/2000/xmlns/";
|
||||
const char STR_XMLNS[] = "xmlns";
|
||||
const char STR_XML[] = "xml";
|
||||
const char STR_VERSION[] = "version";
|
||||
const char STR_ENCODING[] = "encoding";
|
||||
|
||||
const StaticQName QN_XMLNS = { STR_EMPTY, STR_XMLNS };
|
||||
|
||||
} // namespace buzz
|
@ -1,47 +0,0 @@
|
||||
/*
|
||||
* libjingle
|
||||
* Copyright 2004--2005, Google Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef TALK_XMLLITE_XMLCONSTANTS_H_
|
||||
#define TALK_XMLLITE_XMLCONSTANTS_H_
|
||||
|
||||
#include "talk/xmllite/qname.h"
|
||||
|
||||
namespace buzz {
|
||||
|
||||
extern const char STR_EMPTY[];
|
||||
extern const char NS_XML[];
|
||||
extern const char NS_XMLNS[];
|
||||
extern const char STR_XMLNS[];
|
||||
extern const char STR_XML[];
|
||||
extern const char STR_VERSION[];
|
||||
extern const char STR_ENCODING[];
|
||||
|
||||
extern const StaticQName QN_XMLNS;
|
||||
|
||||
} // namespace buzz
|
||||
|
||||
#endif // TALK_XMLLITE_XMLCONSTANTS_H_
|
@ -1,513 +0,0 @@
|
||||
/*
|
||||
* libjingle
|
||||
* Copyright 2004--2005, Google Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "talk/xmllite/xmlelement.h"
|
||||
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "talk/xmllite/qname.h"
|
||||
#include "talk/xmllite/xmlbuilder.h"
|
||||
#include "talk/xmllite/xmlconstants.h"
|
||||
#include "talk/xmllite/xmlparser.h"
|
||||
#include "talk/xmllite/xmlprinter.h"
|
||||
#include "webrtc/base/common.h"
|
||||
|
||||
namespace buzz {
|
||||
|
||||
XmlChild::~XmlChild() {
|
||||
}
|
||||
|
||||
bool XmlText::IsTextImpl() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
XmlElement* XmlText::AsElementImpl() const {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
XmlText* XmlText::AsTextImpl() const {
|
||||
return const_cast<XmlText *>(this);
|
||||
}
|
||||
|
||||
void XmlText::SetText(const std::string& text) {
|
||||
text_ = text;
|
||||
}
|
||||
|
||||
void XmlText::AddParsedText(const char* buf, int len) {
|
||||
text_.append(buf, len);
|
||||
}
|
||||
|
||||
void XmlText::AddText(const std::string& text) {
|
||||
text_ += text;
|
||||
}
|
||||
|
||||
XmlText::~XmlText() {
|
||||
}
|
||||
|
||||
XmlElement::XmlElement(const QName& name) :
|
||||
name_(name),
|
||||
first_attr_(NULL),
|
||||
last_attr_(NULL),
|
||||
first_child_(NULL),
|
||||
last_child_(NULL),
|
||||
cdata_(false) {
|
||||
}
|
||||
|
||||
XmlElement::XmlElement(const XmlElement& elt) :
|
||||
XmlChild(),
|
||||
name_(elt.name_),
|
||||
first_attr_(NULL),
|
||||
last_attr_(NULL),
|
||||
first_child_(NULL),
|
||||
last_child_(NULL),
|
||||
cdata_(false) {
|
||||
|
||||
// copy attributes
|
||||
XmlAttr* attr;
|
||||
XmlAttr ** plast_attr = &first_attr_;
|
||||
XmlAttr* newAttr = NULL;
|
||||
for (attr = elt.first_attr_; attr; attr = attr->NextAttr()) {
|
||||
newAttr = new XmlAttr(*attr);
|
||||
*plast_attr = newAttr;
|
||||
plast_attr = &(newAttr->next_attr_);
|
||||
}
|
||||
last_attr_ = newAttr;
|
||||
|
||||
// copy children
|
||||
XmlChild* pChild;
|
||||
XmlChild ** ppLast = &first_child_;
|
||||
XmlChild* newChild = NULL;
|
||||
|
||||
for (pChild = elt.first_child_; pChild; pChild = pChild->NextChild()) {
|
||||
if (pChild->IsText()) {
|
||||
newChild = new XmlText(*(pChild->AsText()));
|
||||
} else {
|
||||
newChild = new XmlElement(*(pChild->AsElement()));
|
||||
}
|
||||
*ppLast = newChild;
|
||||
ppLast = &(newChild->next_child_);
|
||||
}
|
||||
last_child_ = newChild;
|
||||
|
||||
cdata_ = elt.cdata_;
|
||||
}
|
||||
|
||||
XmlElement::XmlElement(const QName& name, bool useDefaultNs) :
|
||||
name_(name),
|
||||
first_attr_(useDefaultNs ? new XmlAttr(QN_XMLNS, name.Namespace()) : NULL),
|
||||
last_attr_(first_attr_),
|
||||
first_child_(NULL),
|
||||
last_child_(NULL),
|
||||
cdata_(false) {
|
||||
}
|
||||
|
||||
bool XmlElement::IsTextImpl() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
XmlElement* XmlElement::AsElementImpl() const {
|
||||
return const_cast<XmlElement *>(this);
|
||||
}
|
||||
|
||||
XmlText* XmlElement::AsTextImpl() const {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const std::string XmlElement::BodyText() const {
|
||||
if (first_child_ && first_child_->IsText() && last_child_ == first_child_) {
|
||||
return first_child_->AsText()->Text();
|
||||
}
|
||||
|
||||
return std::string();
|
||||
}
|
||||
|
||||
void XmlElement::SetBodyText(const std::string& text) {
|
||||
if (text.empty()) {
|
||||
ClearChildren();
|
||||
} else if (first_child_ == NULL) {
|
||||
AddText(text);
|
||||
} else if (first_child_->IsText() && last_child_ == first_child_) {
|
||||
first_child_->AsText()->SetText(text);
|
||||
} else {
|
||||
ClearChildren();
|
||||
AddText(text);
|
||||
}
|
||||
}
|
||||
|
||||
const QName XmlElement::FirstElementName() const {
|
||||
const XmlElement* element = FirstElement();
|
||||
if (element == NULL)
|
||||
return QName();
|
||||
return element->Name();
|
||||
}
|
||||
|
||||
XmlAttr* XmlElement::FirstAttr() {
|
||||
return first_attr_;
|
||||
}
|
||||
|
||||
const std::string XmlElement::Attr(const StaticQName& name) const {
|
||||
XmlAttr* attr;
|
||||
for (attr = first_attr_; attr; attr = attr->next_attr_) {
|
||||
if (attr->name_ == name)
|
||||
return attr->value_;
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
const std::string XmlElement::Attr(const QName& name) const {
|
||||
XmlAttr* attr;
|
||||
for (attr = first_attr_; attr; attr = attr->next_attr_) {
|
||||
if (attr->name_ == name)
|
||||
return attr->value_;
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
bool XmlElement::HasAttr(const StaticQName& name) const {
|
||||
XmlAttr* attr;
|
||||
for (attr = first_attr_; attr; attr = attr->next_attr_) {
|
||||
if (attr->name_ == name)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool XmlElement::HasAttr(const QName& name) const {
|
||||
XmlAttr* attr;
|
||||
for (attr = first_attr_; attr; attr = attr->next_attr_) {
|
||||
if (attr->name_ == name)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void XmlElement::SetAttr(const QName& name, const std::string& value) {
|
||||
XmlAttr* attr;
|
||||
for (attr = first_attr_; attr; attr = attr->next_attr_) {
|
||||
if (attr->name_ == name)
|
||||
break;
|
||||
}
|
||||
if (!attr) {
|
||||
attr = new XmlAttr(name, value);
|
||||
if (last_attr_)
|
||||
last_attr_->next_attr_ = attr;
|
||||
else
|
||||
first_attr_ = attr;
|
||||
last_attr_ = attr;
|
||||
return;
|
||||
}
|
||||
attr->value_ = value;
|
||||
}
|
||||
|
||||
void XmlElement::ClearAttr(const QName& name) {
|
||||
XmlAttr* attr;
|
||||
XmlAttr* last_attr = NULL;
|
||||
for (attr = first_attr_; attr; attr = attr->next_attr_) {
|
||||
if (attr->name_ == name)
|
||||
break;
|
||||
last_attr = attr;
|
||||
}
|
||||
if (!attr)
|
||||
return;
|
||||
if (!last_attr)
|
||||
first_attr_ = attr->next_attr_;
|
||||
else
|
||||
last_attr->next_attr_ = attr->next_attr_;
|
||||
if (last_attr_ == attr)
|
||||
last_attr_ = last_attr;
|
||||
delete attr;
|
||||
}
|
||||
|
||||
XmlChild* XmlElement::FirstChild() {
|
||||
return first_child_;
|
||||
}
|
||||
|
||||
XmlElement* XmlElement::FirstElement() {
|
||||
XmlChild* pChild;
|
||||
for (pChild = first_child_; pChild; pChild = pChild->next_child_) {
|
||||
if (!pChild->IsText())
|
||||
return pChild->AsElement();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
XmlElement* XmlElement::NextElement() {
|
||||
XmlChild* pChild;
|
||||
for (pChild = next_child_; pChild; pChild = pChild->next_child_) {
|
||||
if (!pChild->IsText())
|
||||
return pChild->AsElement();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
XmlElement* XmlElement::FirstWithNamespace(const std::string& ns) {
|
||||
XmlChild* pChild;
|
||||
for (pChild = first_child_; pChild; pChild = pChild->next_child_) {
|
||||
if (!pChild->IsText() && pChild->AsElement()->Name().Namespace() == ns)
|
||||
return pChild->AsElement();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
XmlElement *
|
||||
XmlElement::NextWithNamespace(const std::string& ns) {
|
||||
XmlChild* pChild;
|
||||
for (pChild = next_child_; pChild; pChild = pChild->next_child_) {
|
||||
if (!pChild->IsText() && pChild->AsElement()->Name().Namespace() == ns)
|
||||
return pChild->AsElement();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
XmlElement *
|
||||
XmlElement::FirstNamed(const QName& name) {
|
||||
XmlChild* pChild;
|
||||
for (pChild = first_child_; pChild; pChild = pChild->next_child_) {
|
||||
if (!pChild->IsText() && pChild->AsElement()->Name() == name)
|
||||
return pChild->AsElement();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
XmlElement *
|
||||
XmlElement::FirstNamed(const StaticQName& name) {
|
||||
XmlChild* pChild;
|
||||
for (pChild = first_child_; pChild; pChild = pChild->next_child_) {
|
||||
if (!pChild->IsText() && pChild->AsElement()->Name() == name)
|
||||
return pChild->AsElement();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
XmlElement *
|
||||
XmlElement::NextNamed(const QName& name) {
|
||||
XmlChild* pChild;
|
||||
for (pChild = next_child_; pChild; pChild = pChild->next_child_) {
|
||||
if (!pChild->IsText() && pChild->AsElement()->Name() == name)
|
||||
return pChild->AsElement();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
XmlElement *
|
||||
XmlElement::NextNamed(const StaticQName& name) {
|
||||
XmlChild* pChild;
|
||||
for (pChild = next_child_; pChild; pChild = pChild->next_child_) {
|
||||
if (!pChild->IsText() && pChild->AsElement()->Name() == name)
|
||||
return pChild->AsElement();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
XmlElement* XmlElement::FindOrAddNamedChild(const QName& name) {
|
||||
XmlElement* child = FirstNamed(name);
|
||||
if (!child) {
|
||||
child = new XmlElement(name);
|
||||
AddElement(child);
|
||||
}
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
const std::string XmlElement::TextNamed(const QName& name) const {
|
||||
XmlChild* pChild;
|
||||
for (pChild = first_child_; pChild; pChild = pChild->next_child_) {
|
||||
if (!pChild->IsText() && pChild->AsElement()->Name() == name)
|
||||
return pChild->AsElement()->BodyText();
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
void XmlElement::InsertChildAfter(XmlChild* predecessor, XmlChild* next) {
|
||||
if (predecessor == NULL) {
|
||||
next->next_child_ = first_child_;
|
||||
first_child_ = next;
|
||||
}
|
||||
else {
|
||||
next->next_child_ = predecessor->next_child_;
|
||||
predecessor->next_child_ = next;
|
||||
}
|
||||
}
|
||||
|
||||
void XmlElement::RemoveChildAfter(XmlChild* predecessor) {
|
||||
XmlChild* next;
|
||||
|
||||
if (predecessor == NULL) {
|
||||
next = first_child_;
|
||||
first_child_ = next->next_child_;
|
||||
}
|
||||
else {
|
||||
next = predecessor->next_child_;
|
||||
predecessor->next_child_ = next->next_child_;
|
||||
}
|
||||
|
||||
if (last_child_ == next)
|
||||
last_child_ = predecessor;
|
||||
|
||||
delete next;
|
||||
}
|
||||
|
||||
void XmlElement::AddAttr(const QName& name, const std::string& value) {
|
||||
ASSERT(!HasAttr(name));
|
||||
|
||||
XmlAttr ** pprev = last_attr_ ? &(last_attr_->next_attr_) : &first_attr_;
|
||||
last_attr_ = (*pprev = new XmlAttr(name, value));
|
||||
}
|
||||
|
||||
void XmlElement::AddAttr(const QName& name, const std::string& value,
|
||||
int depth) {
|
||||
XmlElement* element = this;
|
||||
while (depth--) {
|
||||
element = element->last_child_->AsElement();
|
||||
}
|
||||
element->AddAttr(name, value);
|
||||
}
|
||||
|
||||
void XmlElement::AddParsedText(const char* cstr, int len) {
|
||||
if (len == 0)
|
||||
return;
|
||||
|
||||
if (last_child_ && last_child_->IsText()) {
|
||||
last_child_->AsText()->AddParsedText(cstr, len);
|
||||
return;
|
||||
}
|
||||
XmlChild ** pprev = last_child_ ? &(last_child_->next_child_) : &first_child_;
|
||||
last_child_ = *pprev = new XmlText(cstr, len);
|
||||
}
|
||||
|
||||
void XmlElement::AddCDATAText(const char* buf, int len) {
|
||||
cdata_ = true;
|
||||
AddParsedText(buf, len);
|
||||
}
|
||||
|
||||
void XmlElement::AddText(const std::string& text) {
|
||||
if (text == STR_EMPTY)
|
||||
return;
|
||||
|
||||
if (last_child_ && last_child_->IsText()) {
|
||||
last_child_->AsText()->AddText(text);
|
||||
return;
|
||||
}
|
||||
XmlChild ** pprev = last_child_ ? &(last_child_->next_child_) : &first_child_;
|
||||
last_child_ = *pprev = new XmlText(text);
|
||||
}
|
||||
|
||||
void XmlElement::AddText(const std::string& text, int depth) {
|
||||
// note: the first syntax is ambigious for msvc 6
|
||||
// XmlElement* pel(this);
|
||||
XmlElement* element = this;
|
||||
while (depth--) {
|
||||
element = element->last_child_->AsElement();
|
||||
}
|
||||
element->AddText(text);
|
||||
}
|
||||
|
||||
void XmlElement::AddElement(XmlElement *child) {
|
||||
if (child == NULL)
|
||||
return;
|
||||
|
||||
XmlChild ** pprev = last_child_ ? &(last_child_->next_child_) : &first_child_;
|
||||
*pprev = child;
|
||||
last_child_ = child;
|
||||
child->next_child_ = NULL;
|
||||
}
|
||||
|
||||
void XmlElement::AddElement(XmlElement *child, int depth) {
|
||||
XmlElement* element = this;
|
||||
while (depth--) {
|
||||
element = element->last_child_->AsElement();
|
||||
}
|
||||
element->AddElement(child);
|
||||
}
|
||||
|
||||
void XmlElement::ClearNamedChildren(const QName& name) {
|
||||
XmlChild* prev_child = NULL;
|
||||
XmlChild* next_child;
|
||||
XmlChild* child;
|
||||
for (child = FirstChild(); child; child = next_child) {
|
||||
next_child = child->NextChild();
|
||||
if (!child->IsText() && child->AsElement()->Name() == name)
|
||||
{
|
||||
RemoveChildAfter(prev_child);
|
||||
continue;
|
||||
}
|
||||
prev_child = child;
|
||||
}
|
||||
}
|
||||
|
||||
void XmlElement::ClearAttributes() {
|
||||
XmlAttr* attr;
|
||||
for (attr = first_attr_; attr; ) {
|
||||
XmlAttr* to_delete = attr;
|
||||
attr = attr->next_attr_;
|
||||
delete to_delete;
|
||||
}
|
||||
first_attr_ = last_attr_ = NULL;
|
||||
}
|
||||
|
||||
void XmlElement::ClearChildren() {
|
||||
XmlChild* pchild;
|
||||
for (pchild = first_child_; pchild; ) {
|
||||
XmlChild* to_delete = pchild;
|
||||
pchild = pchild->next_child_;
|
||||
delete to_delete;
|
||||
}
|
||||
first_child_ = last_child_ = NULL;
|
||||
}
|
||||
|
||||
std::string XmlElement::Str() const {
|
||||
std::stringstream ss;
|
||||
XmlPrinter::PrintXml(&ss, this);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
XmlElement* XmlElement::ForStr(const std::string& str) {
|
||||
XmlBuilder builder;
|
||||
XmlParser::ParseXml(&builder, str);
|
||||
return builder.CreateElement();
|
||||
}
|
||||
|
||||
XmlElement::~XmlElement() {
|
||||
XmlAttr* attr;
|
||||
for (attr = first_attr_; attr; ) {
|
||||
XmlAttr* to_delete = attr;
|
||||
attr = attr->next_attr_;
|
||||
delete to_delete;
|
||||
}
|
||||
|
||||
XmlChild* pchild;
|
||||
for (pchild = first_child_; pchild; ) {
|
||||
XmlChild* to_delete = pchild;
|
||||
pchild = pchild->next_child_;
|
||||
delete to_delete;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace buzz
|
@ -1,251 +0,0 @@
|
||||
/*
|
||||
* libjingle
|
||||
* Copyright 2004--2005, Google Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef TALK_XMLLITE_XMLELEMENT_H_
|
||||
#define TALK_XMLLITE_XMLELEMENT_H_
|
||||
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
|
||||
#include "talk/xmllite/qname.h"
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
|
||||
namespace buzz {
|
||||
|
||||
class XmlChild;
|
||||
class XmlText;
|
||||
class XmlElement;
|
||||
class XmlAttr;
|
||||
|
||||
class XmlChild {
|
||||
public:
|
||||
XmlChild* NextChild() { return next_child_; }
|
||||
const XmlChild* NextChild() const { return next_child_; }
|
||||
|
||||
bool IsText() const { return IsTextImpl(); }
|
||||
|
||||
XmlElement* AsElement() { return AsElementImpl(); }
|
||||
const XmlElement* AsElement() const { return AsElementImpl(); }
|
||||
|
||||
XmlText* AsText() { return AsTextImpl(); }
|
||||
const XmlText* AsText() const { return AsTextImpl(); }
|
||||
|
||||
|
||||
protected:
|
||||
XmlChild() :
|
||||
next_child_(NULL) {
|
||||
}
|
||||
|
||||
virtual bool IsTextImpl() const = 0;
|
||||
virtual XmlElement* AsElementImpl() const = 0;
|
||||
virtual XmlText* AsTextImpl() const = 0;
|
||||
|
||||
|
||||
virtual ~XmlChild();
|
||||
|
||||
private:
|
||||
friend class XmlElement;
|
||||
|
||||
XmlChild(const XmlChild& noimpl);
|
||||
|
||||
XmlChild* next_child_;
|
||||
};
|
||||
|
||||
class XmlText : public XmlChild {
|
||||
public:
|
||||
explicit XmlText(const std::string& text) :
|
||||
XmlChild(),
|
||||
text_(text) {
|
||||
}
|
||||
explicit XmlText(const XmlText& t) :
|
||||
XmlChild(),
|
||||
text_(t.text_) {
|
||||
}
|
||||
explicit XmlText(const char* cstr, size_t len) :
|
||||
XmlChild(),
|
||||
text_(cstr, len) {
|
||||
}
|
||||
virtual ~XmlText();
|
||||
|
||||
const std::string& Text() const { return text_; }
|
||||
void SetText(const std::string& text);
|
||||
void AddParsedText(const char* buf, int len);
|
||||
void AddText(const std::string& text);
|
||||
|
||||
protected:
|
||||
virtual bool IsTextImpl() const;
|
||||
virtual XmlElement* AsElementImpl() const;
|
||||
virtual XmlText* AsTextImpl() const;
|
||||
|
||||
private:
|
||||
std::string text_;
|
||||
};
|
||||
|
||||
class XmlAttr {
|
||||
public:
|
||||
XmlAttr* NextAttr() const { return next_attr_; }
|
||||
const QName& Name() const { return name_; }
|
||||
const std::string& Value() const { return value_; }
|
||||
|
||||
private:
|
||||
friend class XmlElement;
|
||||
|
||||
explicit XmlAttr(const QName& name, const std::string& value) :
|
||||
next_attr_(NULL),
|
||||
name_(name),
|
||||
value_(value) {
|
||||
}
|
||||
explicit XmlAttr(const XmlAttr& att) :
|
||||
next_attr_(NULL),
|
||||
name_(att.name_),
|
||||
value_(att.value_) {
|
||||
}
|
||||
|
||||
XmlAttr* next_attr_;
|
||||
QName name_;
|
||||
std::string value_;
|
||||
};
|
||||
|
||||
class XmlElement : public XmlChild {
|
||||
public:
|
||||
explicit XmlElement(const QName& name);
|
||||
explicit XmlElement(const QName& name, bool useDefaultNs);
|
||||
explicit XmlElement(const XmlElement& elt);
|
||||
|
||||
virtual ~XmlElement();
|
||||
|
||||
const QName& Name() const { return name_; }
|
||||
void SetName(const QName& name) { name_ = name; }
|
||||
|
||||
const std::string BodyText() const;
|
||||
void SetBodyText(const std::string& text);
|
||||
|
||||
const QName FirstElementName() const;
|
||||
|
||||
XmlAttr* FirstAttr();
|
||||
const XmlAttr* FirstAttr() const
|
||||
{ return const_cast<XmlElement *>(this)->FirstAttr(); }
|
||||
|
||||
// Attr will return an empty string if the attribute isn't there:
|
||||
// use HasAttr to test presence of an attribute.
|
||||
const std::string Attr(const StaticQName& name) const;
|
||||
const std::string Attr(const QName& name) const;
|
||||
bool HasAttr(const StaticQName& name) const;
|
||||
bool HasAttr(const QName& name) const;
|
||||
void SetAttr(const QName& name, const std::string& value);
|
||||
void ClearAttr(const QName& name);
|
||||
|
||||
XmlChild* FirstChild();
|
||||
const XmlChild* FirstChild() const {
|
||||
return const_cast<XmlElement *>(this)->FirstChild();
|
||||
}
|
||||
|
||||
XmlElement* FirstElement();
|
||||
const XmlElement* FirstElement() const {
|
||||
return const_cast<XmlElement *>(this)->FirstElement();
|
||||
}
|
||||
|
||||
XmlElement* NextElement();
|
||||
const XmlElement* NextElement() const {
|
||||
return const_cast<XmlElement *>(this)->NextElement();
|
||||
}
|
||||
|
||||
XmlElement* FirstWithNamespace(const std::string& ns);
|
||||
const XmlElement* FirstWithNamespace(const std::string& ns) const {
|
||||
return const_cast<XmlElement *>(this)->FirstWithNamespace(ns);
|
||||
}
|
||||
|
||||
XmlElement* NextWithNamespace(const std::string& ns);
|
||||
const XmlElement* NextWithNamespace(const std::string& ns) const {
|
||||
return const_cast<XmlElement *>(this)->NextWithNamespace(ns);
|
||||
}
|
||||
|
||||
XmlElement* FirstNamed(const StaticQName& name);
|
||||
const XmlElement* FirstNamed(const StaticQName& name) const {
|
||||
return const_cast<XmlElement *>(this)->FirstNamed(name);
|
||||
}
|
||||
|
||||
XmlElement* FirstNamed(const QName& name);
|
||||
const XmlElement* FirstNamed(const QName& name) const {
|
||||
return const_cast<XmlElement *>(this)->FirstNamed(name);
|
||||
}
|
||||
|
||||
XmlElement* NextNamed(const StaticQName& name);
|
||||
const XmlElement* NextNamed(const StaticQName& name) const {
|
||||
return const_cast<XmlElement *>(this)->NextNamed(name);
|
||||
}
|
||||
|
||||
XmlElement* NextNamed(const QName& name);
|
||||
const XmlElement* NextNamed(const QName& name) const {
|
||||
return const_cast<XmlElement *>(this)->NextNamed(name);
|
||||
}
|
||||
|
||||
// Finds the first element named 'name'. If that element can't be found then
|
||||
// adds one and returns it.
|
||||
XmlElement* FindOrAddNamedChild(const QName& name);
|
||||
|
||||
const std::string TextNamed(const QName& name) const;
|
||||
|
||||
void InsertChildAfter(XmlChild* predecessor, XmlChild* new_child);
|
||||
void RemoveChildAfter(XmlChild* predecessor);
|
||||
|
||||
void AddParsedText(const char* buf, int len);
|
||||
// Note: CDATA is not supported by XMPP, therefore using this function will
|
||||
// generate non-XMPP compatible XML.
|
||||
void AddCDATAText(const char* buf, int len);
|
||||
void AddText(const std::string& text);
|
||||
void AddText(const std::string& text, int depth);
|
||||
void AddElement(XmlElement* child);
|
||||
void AddElement(XmlElement* child, int depth);
|
||||
void AddAttr(const QName& name, const std::string& value);
|
||||
void AddAttr(const QName& name, const std::string& value, int depth);
|
||||
void ClearNamedChildren(const QName& name);
|
||||
void ClearAttributes();
|
||||
void ClearChildren();
|
||||
|
||||
static XmlElement* ForStr(const std::string& str);
|
||||
std::string Str() const;
|
||||
|
||||
bool IsCDATA() const { return cdata_; }
|
||||
|
||||
protected:
|
||||
virtual bool IsTextImpl() const;
|
||||
virtual XmlElement* AsElementImpl() const;
|
||||
virtual XmlText* AsTextImpl() const;
|
||||
|
||||
private:
|
||||
QName name_;
|
||||
XmlAttr* first_attr_;
|
||||
XmlAttr* last_attr_;
|
||||
XmlChild* first_child_;
|
||||
XmlChild* last_child_;
|
||||
bool cdata_;
|
||||
};
|
||||
|
||||
} // namespace buzz
|
||||
|
||||
#endif // TALK_XMLLITE_XMLELEMENT_H_
|
@ -1,275 +0,0 @@
|
||||
/*
|
||||
* libjingle
|
||||
* Copyright 2004, Google Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include "talk/xmllite/xmlelement.h"
|
||||
#include "webrtc/base/common.h"
|
||||
#include "webrtc/base/gunit.h"
|
||||
#include "webrtc/base/thread.h"
|
||||
|
||||
using buzz::QName;
|
||||
using buzz::XmlAttr;
|
||||
using buzz::XmlChild;
|
||||
using buzz::XmlElement;
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const QName& name) {
|
||||
os << name.Namespace() << ":" << name.LocalPart();
|
||||
return os;
|
||||
}
|
||||
|
||||
TEST(XmlElementTest, TestConstructors) {
|
||||
XmlElement elt(QName("google:test", "first"));
|
||||
EXPECT_EQ("<test:first xmlns:test=\"google:test\"/>", elt.Str());
|
||||
|
||||
XmlElement elt2(QName("google:test", "first"), true);
|
||||
EXPECT_EQ("<first xmlns=\"google:test\"/>", elt2.Str());
|
||||
}
|
||||
|
||||
TEST(XmlElementTest, TestAdd) {
|
||||
XmlElement elt(QName("google:test", "root"), true);
|
||||
elt.AddElement(new XmlElement(QName("google:test", "first")));
|
||||
elt.AddElement(new XmlElement(QName("google:test", "nested")), 1);
|
||||
elt.AddText("nested-value", 2);
|
||||
elt.AddText("between-", 1);
|
||||
elt.AddText("value", 1);
|
||||
elt.AddElement(new XmlElement(QName("google:test", "nested2")), 1);
|
||||
elt.AddElement(new XmlElement(QName("google:test", "second")));
|
||||
elt.AddText("init-value", 1);
|
||||
elt.AddElement(new XmlElement(QName("google:test", "nested3")), 1);
|
||||
elt.AddText("trailing-value", 1);
|
||||
|
||||
// make sure it looks ok overall
|
||||
EXPECT_EQ("<root xmlns=\"google:test\">"
|
||||
"<first><nested>nested-value</nested>between-value<nested2/></first>"
|
||||
"<second>init-value<nested3/>trailing-value</second></root>",
|
||||
elt.Str());
|
||||
|
||||
// make sure text was concatenated
|
||||
XmlChild * pchild =
|
||||
elt.FirstChild()->AsElement()->FirstChild()->NextChild();
|
||||
EXPECT_TRUE(pchild->IsText());
|
||||
EXPECT_EQ("between-value", pchild->AsText()->Text());
|
||||
}
|
||||
|
||||
TEST(XmlElementTest, TestAttrs) {
|
||||
XmlElement elt(QName("", "root"));
|
||||
elt.SetAttr(QName("", "a"), "avalue");
|
||||
EXPECT_EQ("<root a=\"avalue\"/>", elt.Str());
|
||||
|
||||
elt.SetAttr(QName("", "b"), "bvalue");
|
||||
EXPECT_EQ("<root a=\"avalue\" b=\"bvalue\"/>", elt.Str());
|
||||
|
||||
elt.SetAttr(QName("", "a"), "avalue2");
|
||||
EXPECT_EQ("<root a=\"avalue2\" b=\"bvalue\"/>", elt.Str());
|
||||
|
||||
elt.SetAttr(QName("", "b"), "bvalue2");
|
||||
EXPECT_EQ("<root a=\"avalue2\" b=\"bvalue2\"/>", elt.Str());
|
||||
|
||||
elt.SetAttr(QName("", "c"), "cvalue");
|
||||
EXPECT_EQ("<root a=\"avalue2\" b=\"bvalue2\" c=\"cvalue\"/>", elt.Str());
|
||||
|
||||
XmlAttr * patt = elt.FirstAttr();
|
||||
EXPECT_EQ(QName("", "a"), patt->Name());
|
||||
EXPECT_EQ("avalue2", patt->Value());
|
||||
|
||||
patt = patt->NextAttr();
|
||||
EXPECT_EQ(QName("", "b"), patt->Name());
|
||||
EXPECT_EQ("bvalue2", patt->Value());
|
||||
|
||||
patt = patt->NextAttr();
|
||||
EXPECT_EQ(QName("", "c"), patt->Name());
|
||||
EXPECT_EQ("cvalue", patt->Value());
|
||||
|
||||
patt = patt->NextAttr();
|
||||
EXPECT_TRUE(NULL == patt);
|
||||
|
||||
EXPECT_TRUE(elt.HasAttr(QName("", "a")));
|
||||
EXPECT_TRUE(elt.HasAttr(QName("", "b")));
|
||||
EXPECT_TRUE(elt.HasAttr(QName("", "c")));
|
||||
EXPECT_FALSE(elt.HasAttr(QName("", "d")));
|
||||
|
||||
elt.SetAttr(QName("", "d"), "dvalue");
|
||||
EXPECT_EQ("<root a=\"avalue2\" b=\"bvalue2\" c=\"cvalue\" d=\"dvalue\"/>",
|
||||
elt.Str());
|
||||
EXPECT_TRUE(elt.HasAttr(QName("", "d")));
|
||||
|
||||
elt.ClearAttr(QName("", "z")); // not found, no effect
|
||||
EXPECT_EQ("<root a=\"avalue2\" b=\"bvalue2\" c=\"cvalue\" d=\"dvalue\"/>",
|
||||
elt.Str());
|
||||
|
||||
elt.ClearAttr(QName("", "b"));
|
||||
EXPECT_EQ("<root a=\"avalue2\" c=\"cvalue\" d=\"dvalue\"/>", elt.Str());
|
||||
|
||||
elt.ClearAttr(QName("", "a"));
|
||||
EXPECT_EQ("<root c=\"cvalue\" d=\"dvalue\"/>", elt.Str());
|
||||
|
||||
elt.ClearAttr(QName("", "d"));
|
||||
EXPECT_EQ("<root c=\"cvalue\"/>", elt.Str());
|
||||
|
||||
elt.ClearAttr(QName("", "c"));
|
||||
EXPECT_EQ("<root/>", elt.Str());
|
||||
}
|
||||
|
||||
TEST(XmlElementTest, TestBodyText) {
|
||||
XmlElement elt(QName("", "root"));
|
||||
EXPECT_EQ("", elt.BodyText());
|
||||
|
||||
elt.AddText("body value text");
|
||||
|
||||
EXPECT_EQ("body value text", elt.BodyText());
|
||||
|
||||
elt.ClearChildren();
|
||||
elt.AddText("more value ");
|
||||
elt.AddText("text");
|
||||
|
||||
EXPECT_EQ("more value text", elt.BodyText());
|
||||
|
||||
elt.ClearChildren();
|
||||
elt.AddText("decoy");
|
||||
elt.AddElement(new XmlElement(QName("", "dummy")));
|
||||
EXPECT_EQ("", elt.BodyText());
|
||||
|
||||
elt.SetBodyText("replacement");
|
||||
EXPECT_EQ("replacement", elt.BodyText());
|
||||
|
||||
elt.SetBodyText("");
|
||||
EXPECT_TRUE(NULL == elt.FirstChild());
|
||||
|
||||
elt.SetBodyText("goodbye");
|
||||
EXPECT_EQ("goodbye", elt.FirstChild()->AsText()->Text());
|
||||
EXPECT_EQ("goodbye", elt.BodyText());
|
||||
}
|
||||
|
||||
TEST(XmlElementTest, TestCopyConstructor) {
|
||||
XmlElement * element = XmlElement::ForStr(
|
||||
"<root xmlns='test-foo'>This is a <em a='avalue' b='bvalue'>"
|
||||
"little <b>little</b></em> test</root>");
|
||||
|
||||
XmlElement * pelCopy = new XmlElement(*element);
|
||||
EXPECT_EQ("<root xmlns=\"test-foo\">This is a <em a=\"avalue\" b=\"bvalue\">"
|
||||
"little <b>little</b></em> test</root>", pelCopy->Str());
|
||||
delete pelCopy;
|
||||
|
||||
pelCopy = new XmlElement(*(element->FirstChild()->NextChild()->AsElement()));
|
||||
EXPECT_EQ("<foo:em a=\"avalue\" b=\"bvalue\" xmlns:foo=\"test-foo\">"
|
||||
"little <foo:b>little</foo:b></foo:em>", pelCopy->Str());
|
||||
|
||||
XmlAttr * patt = pelCopy->FirstAttr();
|
||||
EXPECT_EQ(QName("", "a"), patt->Name());
|
||||
EXPECT_EQ("avalue", patt->Value());
|
||||
|
||||
patt = patt->NextAttr();
|
||||
EXPECT_EQ(QName("", "b"), patt->Name());
|
||||
EXPECT_EQ("bvalue", patt->Value());
|
||||
|
||||
patt = patt->NextAttr();
|
||||
EXPECT_TRUE(NULL == patt);
|
||||
delete pelCopy;
|
||||
delete element;
|
||||
}
|
||||
|
||||
TEST(XmlElementTest, TestNameSearch) {
|
||||
XmlElement * element = XmlElement::ForStr(
|
||||
"<root xmlns='test-foo'>"
|
||||
"<firstname>George</firstname>"
|
||||
"<middlename>X.</middlename>"
|
||||
"some text"
|
||||
"<lastname>Harrison</lastname>"
|
||||
"<firstname>John</firstname>"
|
||||
"<middlename>Y.</middlename>"
|
||||
"<lastname>Lennon</lastname>"
|
||||
"</root>");
|
||||
EXPECT_TRUE(NULL ==
|
||||
element->FirstNamed(QName("", "firstname")));
|
||||
EXPECT_EQ(element->FirstChild(),
|
||||
element->FirstNamed(QName("test-foo", "firstname")));
|
||||
EXPECT_EQ(element->FirstChild()->NextChild(),
|
||||
element->FirstNamed(QName("test-foo", "middlename")));
|
||||
EXPECT_EQ(element->FirstElement()->NextElement(),
|
||||
element->FirstNamed(QName("test-foo", "middlename")));
|
||||
EXPECT_EQ("Harrison",
|
||||
element->TextNamed(QName("test-foo", "lastname")));
|
||||
EXPECT_EQ(element->FirstElement()->NextElement()->NextElement(),
|
||||
element->FirstNamed(QName("test-foo", "lastname")));
|
||||
EXPECT_EQ("John", element->FirstNamed(QName("test-foo", "firstname"))->
|
||||
NextNamed(QName("test-foo", "firstname"))->BodyText());
|
||||
EXPECT_EQ("Y.", element->FirstNamed(QName("test-foo", "middlename"))->
|
||||
NextNamed(QName("test-foo", "middlename"))->BodyText());
|
||||
EXPECT_EQ("Lennon", element->FirstNamed(QName("test-foo", "lastname"))->
|
||||
NextNamed(QName("test-foo", "lastname"))->BodyText());
|
||||
EXPECT_TRUE(NULL == element->FirstNamed(QName("test-foo", "firstname"))->
|
||||
NextNamed(QName("test-foo", "firstname"))->
|
||||
NextNamed(QName("test-foo", "firstname")));
|
||||
|
||||
delete element;
|
||||
}
|
||||
|
||||
class XmlElementCreatorThread : public rtc::Thread {
|
||||
public:
|
||||
XmlElementCreatorThread(int count, buzz::QName qname) :
|
||||
count_(count), qname_(qname) {}
|
||||
|
||||
virtual ~XmlElementCreatorThread() {
|
||||
Stop();
|
||||
}
|
||||
|
||||
virtual void Run() {
|
||||
std::vector<buzz::XmlElement*> elems;
|
||||
for (int i = 0; i < count_; i++) {
|
||||
elems.push_back(new XmlElement(qname_));
|
||||
}
|
||||
for (int i = 0; i < count_; i++) {
|
||||
delete elems[i];
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
int count_;
|
||||
buzz::QName qname_;
|
||||
};
|
||||
|
||||
// If XmlElement creation and destruction isn't thread safe,
|
||||
// this test should crash.
|
||||
TEST(XmlElementTest, TestMultithread) {
|
||||
int thread_count = 2; // Was 100, but that's too slow.
|
||||
int elem_count = 100; // Was 100000, but that's too slow.
|
||||
buzz::QName qname("foo", "bar");
|
||||
|
||||
std::vector<rtc::Thread*> threads;
|
||||
for (int i = 0; i < thread_count; i++) {
|
||||
threads.push_back(
|
||||
new XmlElementCreatorThread(elem_count, qname));
|
||||
threads[i]->Start();
|
||||
}
|
||||
|
||||
for (int i = 0; i < thread_count; i++) {
|
||||
threads[i]->Stop();
|
||||
delete threads[i];
|
||||
}
|
||||
}
|
@ -1,195 +0,0 @@
|
||||
/*
|
||||
* libjingle
|
||||
* Copyright 2004--2005, Google Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "talk/xmllite/xmlnsstack.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "talk/xmllite/xmlconstants.h"
|
||||
#include "talk/xmllite/xmlelement.h"
|
||||
|
||||
namespace buzz {
|
||||
|
||||
XmlnsStack::XmlnsStack() :
|
||||
pxmlnsStack_(new std::vector<std::string>),
|
||||
pxmlnsDepthStack_(new std::vector<size_t>) {
|
||||
}
|
||||
|
||||
XmlnsStack::~XmlnsStack() {}
|
||||
|
||||
void XmlnsStack::PushFrame() {
|
||||
pxmlnsDepthStack_->push_back(pxmlnsStack_->size());
|
||||
}
|
||||
|
||||
void XmlnsStack::PopFrame() {
|
||||
size_t prev_size = pxmlnsDepthStack_->back();
|
||||
pxmlnsDepthStack_->pop_back();
|
||||
if (prev_size < pxmlnsStack_->size()) {
|
||||
pxmlnsStack_->erase(pxmlnsStack_->begin() + prev_size,
|
||||
pxmlnsStack_->end());
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<std::string, bool> XmlnsStack::NsForPrefix(
|
||||
const std::string& prefix) {
|
||||
if (prefix.length() >= 3 &&
|
||||
(prefix[0] == 'x' || prefix[0] == 'X') &&
|
||||
(prefix[1] == 'm' || prefix[1] == 'M') &&
|
||||
(prefix[2] == 'l' || prefix[2] == 'L')) {
|
||||
if (prefix == "xml")
|
||||
return std::make_pair(NS_XML, true);
|
||||
if (prefix == "xmlns")
|
||||
return std::make_pair(NS_XMLNS, true);
|
||||
// Other names with xml prefix are illegal.
|
||||
return std::make_pair(STR_EMPTY, false);
|
||||
}
|
||||
|
||||
std::vector<std::string>::iterator pos;
|
||||
for (pos = pxmlnsStack_->end(); pos > pxmlnsStack_->begin(); ) {
|
||||
pos -= 2;
|
||||
if (*pos == prefix)
|
||||
return std::make_pair(*(pos + 1), true);
|
||||
}
|
||||
|
||||
if (prefix == STR_EMPTY)
|
||||
return std::make_pair(STR_EMPTY, true); // default namespace
|
||||
|
||||
return std::make_pair(STR_EMPTY, false); // none found
|
||||
}
|
||||
|
||||
bool XmlnsStack::PrefixMatchesNs(const std::string& prefix,
|
||||
const std::string& ns) {
|
||||
const std::pair<std::string, bool> match = NsForPrefix(prefix);
|
||||
return match.second && (match.first == ns);
|
||||
}
|
||||
|
||||
std::pair<std::string, bool> XmlnsStack::PrefixForNs(const std::string& ns,
|
||||
bool isattr) {
|
||||
if (ns == NS_XML)
|
||||
return std::make_pair(std::string("xml"), true);
|
||||
if (ns == NS_XMLNS)
|
||||
return std::make_pair(std::string("xmlns"), true);
|
||||
if (isattr ? ns == STR_EMPTY : PrefixMatchesNs(STR_EMPTY, ns))
|
||||
return std::make_pair(STR_EMPTY, true);
|
||||
|
||||
std::vector<std::string>::iterator pos;
|
||||
for (pos = pxmlnsStack_->end(); pos > pxmlnsStack_->begin(); ) {
|
||||
pos -= 2;
|
||||
if (*(pos + 1) == ns &&
|
||||
(!isattr || !pos->empty()) && PrefixMatchesNs(*pos, ns))
|
||||
return std::make_pair(*pos, true);
|
||||
}
|
||||
|
||||
return std::make_pair(STR_EMPTY, false); // none found
|
||||
}
|
||||
|
||||
std::string XmlnsStack::FormatQName(const QName& name, bool isAttr) {
|
||||
std::string prefix(PrefixForNs(name.Namespace(), isAttr).first);
|
||||
if (prefix == STR_EMPTY)
|
||||
return name.LocalPart();
|
||||
else
|
||||
return prefix + ':' + name.LocalPart();
|
||||
}
|
||||
|
||||
void XmlnsStack::AddXmlns(const std::string & prefix, const std::string & ns) {
|
||||
pxmlnsStack_->push_back(prefix);
|
||||
pxmlnsStack_->push_back(ns);
|
||||
}
|
||||
|
||||
void XmlnsStack::RemoveXmlns() {
|
||||
pxmlnsStack_->pop_back();
|
||||
pxmlnsStack_->pop_back();
|
||||
}
|
||||
|
||||
static bool IsAsciiLetter(char ch) {
|
||||
return ((ch >= 'a' && ch <= 'z') ||
|
||||
(ch >= 'A' && ch <= 'Z'));
|
||||
}
|
||||
|
||||
static std::string AsciiLower(const std::string & s) {
|
||||
std::string result(s);
|
||||
size_t i;
|
||||
for (i = 0; i < result.length(); i++) {
|
||||
if (result[i] >= 'A' && result[i] <= 'Z')
|
||||
result[i] += 'a' - 'A';
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static std::string SuggestPrefix(const std::string & ns) {
|
||||
size_t len = ns.length();
|
||||
size_t i = ns.find_last_of('.');
|
||||
if (i != std::string::npos && len - i <= 4 + 1)
|
||||
len = i; // chop off ".html" or ".xsd" or ".?{0,4}"
|
||||
size_t last = len;
|
||||
while (last > 0) {
|
||||
last -= 1;
|
||||
if (IsAsciiLetter(ns[last])) {
|
||||
size_t first = last;
|
||||
last += 1;
|
||||
while (first > 0) {
|
||||
if (!IsAsciiLetter(ns[first - 1]))
|
||||
break;
|
||||
first -= 1;
|
||||
}
|
||||
if (last - first > 4)
|
||||
last = first + 3;
|
||||
std::string candidate(AsciiLower(ns.substr(first, last - first)));
|
||||
if (candidate.find("xml") != 0)
|
||||
return candidate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return "ns";
|
||||
}
|
||||
|
||||
std::pair<std::string, bool> XmlnsStack::AddNewPrefix(const std::string& ns,
|
||||
bool isAttr) {
|
||||
if (PrefixForNs(ns, isAttr).second)
|
||||
return std::make_pair(STR_EMPTY, false);
|
||||
|
||||
std::string base(SuggestPrefix(ns));
|
||||
std::string result(base);
|
||||
int i = 2;
|
||||
while (NsForPrefix(result).second) {
|
||||
std::stringstream ss;
|
||||
ss << base;
|
||||
ss << (i++);
|
||||
ss >> result;
|
||||
}
|
||||
AddXmlns(result, ns);
|
||||
return std::make_pair(result, true);
|
||||
}
|
||||
|
||||
void XmlnsStack::Reset() {
|
||||
pxmlnsStack_->clear();
|
||||
pxmlnsDepthStack_->clear();
|
||||
}
|
||||
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
/*
|
||||
* libjingle
|
||||
* Copyright 2004--2005, Google Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef TALK_XMLLITE_XMLNSSTACK_H_
|
||||
#define TALK_XMLLITE_XMLNSSTACK_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "talk/xmllite/qname.h"
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
|
||||
namespace buzz {
|
||||
|
||||
class XmlnsStack {
|
||||
public:
|
||||
XmlnsStack();
|
||||
~XmlnsStack();
|
||||
|
||||
void AddXmlns(const std::string& prefix, const std::string& ns);
|
||||
void RemoveXmlns();
|
||||
void PushFrame();
|
||||
void PopFrame();
|
||||
void Reset();
|
||||
|
||||
std::pair<std::string, bool> NsForPrefix(const std::string& prefix);
|
||||
bool PrefixMatchesNs(const std::string & prefix, const std::string & ns);
|
||||
std::pair<std::string, bool> PrefixForNs(const std::string& ns, bool isAttr);
|
||||
std::pair<std::string, bool> AddNewPrefix(const std::string& ns, bool isAttr);
|
||||
std::string FormatQName(const QName & name, bool isAttr);
|
||||
|
||||
private:
|
||||
|
||||
rtc::scoped_ptr<std::vector<std::string> > pxmlnsStack_;
|
||||
rtc::scoped_ptr<std::vector<size_t> > pxmlnsDepthStack_;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TALK_XMLLITE_XMLNSSTACK_H_
|
@ -1,258 +0,0 @@
|
||||
/*
|
||||
* libjingle
|
||||
* Copyright 2004, Google Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "talk/xmllite/xmlnsstack.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "talk/xmllite/xmlconstants.h"
|
||||
#include "webrtc/base/common.h"
|
||||
#include "webrtc/base/gunit.h"
|
||||
|
||||
using buzz::NS_XML;
|
||||
using buzz::NS_XMLNS;
|
||||
using buzz::QName;
|
||||
using buzz::XmlnsStack;
|
||||
|
||||
TEST(XmlnsStackTest, TestBuiltin) {
|
||||
XmlnsStack stack;
|
||||
|
||||
EXPECT_EQ(std::string(NS_XML), stack.NsForPrefix("xml").first);
|
||||
EXPECT_EQ(std::string(NS_XMLNS), stack.NsForPrefix("xmlns").first);
|
||||
EXPECT_EQ("", stack.NsForPrefix("").first);
|
||||
|
||||
EXPECT_EQ("xml", stack.PrefixForNs(NS_XML, false).first);
|
||||
EXPECT_EQ("xmlns", stack.PrefixForNs(NS_XMLNS, false).first);
|
||||
EXPECT_EQ("", stack.PrefixForNs("", false).first);
|
||||
EXPECT_EQ("", stack.PrefixForNs("", true).first);
|
||||
}
|
||||
|
||||
TEST(XmlnsStackTest, TestNsForPrefix) {
|
||||
XmlnsStack stack;
|
||||
stack.AddXmlns("pre1", "ns1");
|
||||
stack.AddXmlns("pre2", "ns2");
|
||||
stack.AddXmlns("pre1", "ns3");
|
||||
stack.AddXmlns("", "ns4");
|
||||
|
||||
EXPECT_EQ("ns3", stack.NsForPrefix("pre1").first);
|
||||
EXPECT_TRUE(stack.NsForPrefix("pre1").second);
|
||||
EXPECT_EQ("ns2", stack.NsForPrefix("pre2").first);
|
||||
EXPECT_EQ("ns4", stack.NsForPrefix("").first);
|
||||
EXPECT_EQ("", stack.NsForPrefix("pre3").first);
|
||||
EXPECT_FALSE(stack.NsForPrefix("pre3").second);
|
||||
}
|
||||
|
||||
TEST(XmlnsStackTest, TestPrefixForNs) {
|
||||
XmlnsStack stack;
|
||||
stack.AddXmlns("pre1", "ns1");
|
||||
stack.AddXmlns("pre2", "ns2");
|
||||
stack.AddXmlns("pre1", "ns3");
|
||||
stack.AddXmlns("pre3", "ns2");
|
||||
stack.AddXmlns("pre4", "ns4");
|
||||
stack.AddXmlns("", "ns4");
|
||||
|
||||
EXPECT_EQ("", stack.PrefixForNs("ns1", false).first);
|
||||
EXPECT_FALSE(stack.PrefixForNs("ns1", false).second);
|
||||
EXPECT_EQ("", stack.PrefixForNs("ns1", true).first);
|
||||
EXPECT_FALSE(stack.PrefixForNs("ns1", true).second);
|
||||
EXPECT_EQ("pre3", stack.PrefixForNs("ns2", false).first);
|
||||
EXPECT_TRUE(stack.PrefixForNs("ns2", false).second);
|
||||
EXPECT_EQ("pre3", stack.PrefixForNs("ns2", true).first);
|
||||
EXPECT_TRUE(stack.PrefixForNs("ns2", true).second);
|
||||
EXPECT_EQ("pre1", stack.PrefixForNs("ns3", false).first);
|
||||
EXPECT_EQ("pre1", stack.PrefixForNs("ns3", true).first);
|
||||
EXPECT_EQ("", stack.PrefixForNs("ns4", false).first);
|
||||
EXPECT_TRUE(stack.PrefixForNs("ns4", false).second);
|
||||
EXPECT_EQ("pre4", stack.PrefixForNs("ns4", true).first);
|
||||
EXPECT_EQ("", stack.PrefixForNs("ns5", false).first);
|
||||
EXPECT_FALSE(stack.PrefixForNs("ns5", false).second);
|
||||
EXPECT_EQ("", stack.PrefixForNs("ns5", true).first);
|
||||
EXPECT_EQ("", stack.PrefixForNs("", false).first);
|
||||
EXPECT_EQ("", stack.PrefixForNs("", true).first);
|
||||
|
||||
stack.AddXmlns("", "ns6");
|
||||
EXPECT_EQ("", stack.PrefixForNs("ns6", false).first);
|
||||
EXPECT_TRUE(stack.PrefixForNs("ns6", false).second);
|
||||
EXPECT_EQ("", stack.PrefixForNs("ns6", true).first);
|
||||
EXPECT_FALSE(stack.PrefixForNs("ns6", true).second);
|
||||
}
|
||||
|
||||
TEST(XmlnsStackTest, TestFrames) {
|
||||
XmlnsStack stack;
|
||||
stack.PushFrame();
|
||||
stack.AddXmlns("pre1", "ns1");
|
||||
stack.AddXmlns("pre2", "ns2");
|
||||
|
||||
stack.PushFrame();
|
||||
stack.AddXmlns("pre1", "ns3");
|
||||
stack.AddXmlns("pre3", "ns2");
|
||||
stack.AddXmlns("pre4", "ns4");
|
||||
|
||||
stack.PushFrame();
|
||||
stack.PushFrame();
|
||||
stack.AddXmlns("", "ns4");
|
||||
|
||||
// basic test
|
||||
EXPECT_EQ("ns3", stack.NsForPrefix("pre1").first);
|
||||
EXPECT_EQ("ns2", stack.NsForPrefix("pre2").first);
|
||||
EXPECT_EQ("ns2", stack.NsForPrefix("pre3").first);
|
||||
EXPECT_EQ("ns4", stack.NsForPrefix("pre4").first);
|
||||
EXPECT_EQ("", stack.NsForPrefix("pre5").first);
|
||||
EXPECT_FALSE(stack.NsForPrefix("pre5").second);
|
||||
EXPECT_EQ("ns4", stack.NsForPrefix("").first);
|
||||
EXPECT_TRUE(stack.NsForPrefix("").second);
|
||||
|
||||
// pop the default xmlns definition
|
||||
stack.PopFrame();
|
||||
EXPECT_EQ("ns3", stack.NsForPrefix("pre1").first);
|
||||
EXPECT_EQ("ns2", stack.NsForPrefix("pre2").first);
|
||||
EXPECT_EQ("ns2", stack.NsForPrefix("pre3").first);
|
||||
EXPECT_EQ("ns4", stack.NsForPrefix("pre4").first);
|
||||
EXPECT_EQ("", stack.NsForPrefix("pre5").first);
|
||||
EXPECT_FALSE(stack.NsForPrefix("pre5").second);
|
||||
EXPECT_EQ("", stack.NsForPrefix("").first);
|
||||
EXPECT_TRUE(stack.NsForPrefix("").second);
|
||||
|
||||
// pop empty frame (nop)
|
||||
stack.PopFrame();
|
||||
EXPECT_EQ("ns3", stack.NsForPrefix("pre1").first);
|
||||
EXPECT_EQ("ns2", stack.NsForPrefix("pre2").first);
|
||||
EXPECT_EQ("ns2", stack.NsForPrefix("pre3").first);
|
||||
EXPECT_EQ("ns4", stack.NsForPrefix("pre4").first);
|
||||
EXPECT_EQ("", stack.NsForPrefix("pre5").first);
|
||||
EXPECT_FALSE(stack.NsForPrefix("pre5").second);
|
||||
EXPECT_EQ("", stack.NsForPrefix("").first);
|
||||
EXPECT_TRUE(stack.NsForPrefix("").second);
|
||||
|
||||
// pop frame with three defs
|
||||
stack.PopFrame();
|
||||
EXPECT_EQ("ns1", stack.NsForPrefix("pre1").first);
|
||||
EXPECT_EQ("ns2", stack.NsForPrefix("pre2").first);
|
||||
EXPECT_EQ("", stack.NsForPrefix("pre3").first);
|
||||
EXPECT_FALSE(stack.NsForPrefix("pre3").second);
|
||||
EXPECT_EQ("", stack.NsForPrefix("pre4").first);
|
||||
EXPECT_FALSE(stack.NsForPrefix("pre4").second);
|
||||
EXPECT_EQ("", stack.NsForPrefix("pre5").first);
|
||||
EXPECT_FALSE(stack.NsForPrefix("pre5").second);
|
||||
EXPECT_EQ("", stack.NsForPrefix("").first);
|
||||
EXPECT_TRUE(stack.NsForPrefix("").second);
|
||||
|
||||
// pop frame with last two defs
|
||||
stack.PopFrame();
|
||||
EXPECT_FALSE(stack.NsForPrefix("pre1").second);
|
||||
EXPECT_FALSE(stack.NsForPrefix("pre2").second);
|
||||
EXPECT_FALSE(stack.NsForPrefix("pre3").second);
|
||||
EXPECT_FALSE(stack.NsForPrefix("pre4").second);
|
||||
EXPECT_FALSE(stack.NsForPrefix("pre5").second);
|
||||
EXPECT_TRUE(stack.NsForPrefix("").second);
|
||||
EXPECT_EQ("", stack.NsForPrefix("pre1").first);
|
||||
EXPECT_EQ("", stack.NsForPrefix("pre2").first);
|
||||
EXPECT_EQ("", stack.NsForPrefix("pre3").first);
|
||||
EXPECT_EQ("", stack.NsForPrefix("pre4").first);
|
||||
EXPECT_EQ("", stack.NsForPrefix("pre5").first);
|
||||
EXPECT_EQ("", stack.NsForPrefix("").first);
|
||||
}
|
||||
|
||||
TEST(XmlnsStackTest, TestAddNewPrefix) {
|
||||
XmlnsStack stack;
|
||||
|
||||
// builtin namespaces cannot be added
|
||||
EXPECT_FALSE(stack.AddNewPrefix("", true).second);
|
||||
EXPECT_FALSE(stack.AddNewPrefix("", false).second);
|
||||
EXPECT_FALSE(stack.AddNewPrefix(NS_XML, true).second);
|
||||
EXPECT_FALSE(stack.AddNewPrefix(NS_XML, false).second);
|
||||
EXPECT_FALSE(stack.AddNewPrefix(NS_XMLNS, true).second);
|
||||
EXPECT_FALSE(stack.AddNewPrefix(NS_XMLNS, false).second);
|
||||
|
||||
// namespaces already added cannot be added again.
|
||||
EXPECT_EQ("foo", stack.AddNewPrefix("http://a.b.com/foo.htm", true).first);
|
||||
EXPECT_EQ("bare", stack.AddNewPrefix("http://a.b.com/bare", false).first);
|
||||
EXPECT_EQ("z", stack.AddNewPrefix("z", false).first);
|
||||
EXPECT_FALSE(stack.AddNewPrefix("http://a.b.com/foo.htm", true).second);
|
||||
EXPECT_FALSE(stack.AddNewPrefix("http://a.b.com/bare", true).second);
|
||||
EXPECT_FALSE(stack.AddNewPrefix("z", true).second);
|
||||
EXPECT_FALSE(stack.AddNewPrefix("http://a.b.com/foo.htm", false).second);
|
||||
EXPECT_FALSE(stack.AddNewPrefix("http://a.b.com/bare", false).second);
|
||||
EXPECT_FALSE(stack.AddNewPrefix("z", false).second);
|
||||
|
||||
// default namespace usable by non-attributes only
|
||||
stack.AddXmlns("", "http://my/default");
|
||||
EXPECT_FALSE(stack.AddNewPrefix("http://my/default", false).second);
|
||||
EXPECT_EQ("def", stack.AddNewPrefix("http://my/default", true).first);
|
||||
|
||||
// namespace cannot start with 'xml'
|
||||
EXPECT_EQ("ns", stack.AddNewPrefix("http://a.b.com/xmltest", true).first);
|
||||
EXPECT_EQ("ns2", stack.AddNewPrefix("xmlagain", false).first);
|
||||
|
||||
// verify added namespaces are still defined
|
||||
EXPECT_EQ("http://a.b.com/foo.htm", stack.NsForPrefix("foo").first);
|
||||
EXPECT_TRUE(stack.NsForPrefix("foo").second);
|
||||
EXPECT_EQ("http://a.b.com/bare", stack.NsForPrefix("bare").first);
|
||||
EXPECT_TRUE(stack.NsForPrefix("bare").second);
|
||||
EXPECT_EQ("z", stack.NsForPrefix("z").first);
|
||||
EXPECT_TRUE(stack.NsForPrefix("z").second);
|
||||
EXPECT_EQ("http://my/default", stack.NsForPrefix("").first);
|
||||
EXPECT_TRUE(stack.NsForPrefix("").second);
|
||||
EXPECT_EQ("http://my/default", stack.NsForPrefix("def").first);
|
||||
EXPECT_TRUE(stack.NsForPrefix("def").second);
|
||||
EXPECT_EQ("http://a.b.com/xmltest", stack.NsForPrefix("ns").first);
|
||||
EXPECT_TRUE(stack.NsForPrefix("ns").second);
|
||||
EXPECT_EQ("xmlagain", stack.NsForPrefix("ns2").first);
|
||||
EXPECT_TRUE(stack.NsForPrefix("ns2").second);
|
||||
}
|
||||
|
||||
TEST(XmlnsStackTest, TestFormatQName) {
|
||||
XmlnsStack stack;
|
||||
stack.AddXmlns("pre1", "ns1");
|
||||
stack.AddXmlns("pre2", "ns2");
|
||||
stack.AddXmlns("pre1", "ns3");
|
||||
stack.AddXmlns("", "ns4");
|
||||
|
||||
EXPECT_EQ("zip",
|
||||
stack.FormatQName(QName("ns1", "zip"), false)); // no match
|
||||
EXPECT_EQ("pre2:abracadabra",
|
||||
stack.FormatQName(QName("ns2", "abracadabra"), false));
|
||||
EXPECT_EQ("pre1:a",
|
||||
stack.FormatQName(QName("ns3", "a"), false));
|
||||
EXPECT_EQ("simple",
|
||||
stack.FormatQName(QName("ns4", "simple"), false));
|
||||
EXPECT_EQ("root",
|
||||
stack.FormatQName(QName("", "root"), false)); // no match
|
||||
|
||||
EXPECT_EQ("zip",
|
||||
stack.FormatQName(QName("ns1", "zip"), true)); // no match
|
||||
EXPECT_EQ("pre2:abracadabra",
|
||||
stack.FormatQName(QName("ns2", "abracadabra"), true));
|
||||
EXPECT_EQ("pre1:a",
|
||||
stack.FormatQName(QName("ns3", "a"), true));
|
||||
EXPECT_EQ("simple",
|
||||
stack.FormatQName(QName("ns4", "simple"), true)); // no match
|
||||
EXPECT_EQ("root",
|
||||
stack.FormatQName(QName("", "root"), true));
|
||||
}
|
@ -1,278 +0,0 @@
|
||||
/*
|
||||
* libjingle
|
||||
* Copyright 2004--2005, Google Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "talk/xmllite/xmlparser.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "talk/xmllite/xmlconstants.h"
|
||||
#include "talk/xmllite/xmlelement.h"
|
||||
#include "talk/xmllite/xmlnsstack.h"
|
||||
#include "talk/xmllite/xmlnsstack.h"
|
||||
#include "webrtc/base/common.h"
|
||||
|
||||
namespace buzz {
|
||||
|
||||
|
||||
static void
|
||||
StartElementCallback(void * userData, const char *name, const char **atts) {
|
||||
(static_cast<XmlParser *>(userData))->ExpatStartElement(name, atts);
|
||||
}
|
||||
|
||||
static void
|
||||
EndElementCallback(void * userData, const char *name) {
|
||||
(static_cast<XmlParser *>(userData))->ExpatEndElement(name);
|
||||
}
|
||||
|
||||
static void
|
||||
CharacterDataCallback(void * userData, const char *text, int len) {
|
||||
(static_cast<XmlParser *>(userData))->ExpatCharacterData(text, len);
|
||||
}
|
||||
|
||||
static void
|
||||
XmlDeclCallback(void * userData, const char * ver, const char * enc, int st) {
|
||||
(static_cast<XmlParser *>(userData))->ExpatXmlDecl(ver, enc, st);
|
||||
}
|
||||
|
||||
XmlParser::XmlParser(XmlParseHandler *pxph) :
|
||||
pxph_(pxph), sentError_(false) {
|
||||
expat_ = XML_ParserCreate(NULL);
|
||||
XML_SetUserData(expat_, this);
|
||||
XML_SetElementHandler(expat_, StartElementCallback, EndElementCallback);
|
||||
XML_SetCharacterDataHandler(expat_, CharacterDataCallback);
|
||||
XML_SetXmlDeclHandler(expat_, XmlDeclCallback);
|
||||
}
|
||||
|
||||
void
|
||||
XmlParser::Reset() {
|
||||
if (!XML_ParserReset(expat_, NULL)) {
|
||||
XML_ParserFree(expat_);
|
||||
expat_ = XML_ParserCreate(NULL);
|
||||
}
|
||||
XML_SetUserData(expat_, this);
|
||||
XML_SetElementHandler(expat_, StartElementCallback, EndElementCallback);
|
||||
XML_SetCharacterDataHandler(expat_, CharacterDataCallback);
|
||||
XML_SetXmlDeclHandler(expat_, XmlDeclCallback);
|
||||
context_.Reset();
|
||||
sentError_ = false;
|
||||
}
|
||||
|
||||
static bool
|
||||
XmlParser_StartsWithXmlns(const char *name) {
|
||||
return name[0] == 'x' &&
|
||||
name[1] == 'm' &&
|
||||
name[2] == 'l' &&
|
||||
name[3] == 'n' &&
|
||||
name[4] == 's';
|
||||
}
|
||||
|
||||
void
|
||||
XmlParser::ExpatStartElement(const char *name, const char **atts) {
|
||||
if (context_.RaisedError() != XML_ERROR_NONE)
|
||||
return;
|
||||
const char **att;
|
||||
context_.StartElement();
|
||||
for (att = atts; *att; att += 2) {
|
||||
if (XmlParser_StartsWithXmlns(*att)) {
|
||||
if ((*att)[5] == '\0') {
|
||||
context_.StartNamespace("", *(att + 1));
|
||||
}
|
||||
else if ((*att)[5] == ':') {
|
||||
if (**(att + 1) == '\0') {
|
||||
// In XML 1.0 empty namespace illegal with prefix (not in 1.1)
|
||||
context_.RaiseError(XML_ERROR_SYNTAX);
|
||||
return;
|
||||
}
|
||||
context_.StartNamespace((*att) + 6, *(att + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
context_.SetPosition(XML_GetCurrentLineNumber(expat_),
|
||||
XML_GetCurrentColumnNumber(expat_),
|
||||
XML_GetCurrentByteIndex(expat_));
|
||||
pxph_->StartElement(&context_, name, atts);
|
||||
}
|
||||
|
||||
void
|
||||
XmlParser::ExpatEndElement(const char *name) {
|
||||
if (context_.RaisedError() != XML_ERROR_NONE)
|
||||
return;
|
||||
context_.EndElement();
|
||||
context_.SetPosition(XML_GetCurrentLineNumber(expat_),
|
||||
XML_GetCurrentColumnNumber(expat_),
|
||||
XML_GetCurrentByteIndex(expat_));
|
||||
pxph_->EndElement(&context_, name);
|
||||
}
|
||||
|
||||
void
|
||||
XmlParser::ExpatCharacterData(const char *text, int len) {
|
||||
if (context_.RaisedError() != XML_ERROR_NONE)
|
||||
return;
|
||||
context_.SetPosition(XML_GetCurrentLineNumber(expat_),
|
||||
XML_GetCurrentColumnNumber(expat_),
|
||||
XML_GetCurrentByteIndex(expat_));
|
||||
pxph_->CharacterData(&context_, text, len);
|
||||
}
|
||||
|
||||
void
|
||||
XmlParser::ExpatXmlDecl(const char * ver, const char * enc, int standalone) {
|
||||
if (context_.RaisedError() != XML_ERROR_NONE)
|
||||
return;
|
||||
|
||||
if (ver && std::string("1.0") != ver) {
|
||||
context_.RaiseError(XML_ERROR_SYNTAX);
|
||||
return;
|
||||
}
|
||||
|
||||
if (standalone == 0) {
|
||||
context_.RaiseError(XML_ERROR_SYNTAX);
|
||||
return;
|
||||
}
|
||||
|
||||
if (enc && !((enc[0] == 'U' || enc[0] == 'u') &&
|
||||
(enc[1] == 'T' || enc[1] == 't') &&
|
||||
(enc[2] == 'F' || enc[2] == 'f') &&
|
||||
enc[3] == '-' && enc[4] =='8')) {
|
||||
context_.RaiseError(XML_ERROR_INCORRECT_ENCODING);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool
|
||||
XmlParser::Parse(const char *data, size_t len, bool isFinal) {
|
||||
if (sentError_)
|
||||
return false;
|
||||
|
||||
if (XML_Parse(expat_, data, static_cast<int>(len), isFinal) !=
|
||||
XML_STATUS_OK) {
|
||||
context_.SetPosition(XML_GetCurrentLineNumber(expat_),
|
||||
XML_GetCurrentColumnNumber(expat_),
|
||||
XML_GetCurrentByteIndex(expat_));
|
||||
context_.RaiseError(XML_GetErrorCode(expat_));
|
||||
}
|
||||
|
||||
if (context_.RaisedError() != XML_ERROR_NONE) {
|
||||
sentError_ = true;
|
||||
pxph_->Error(&context_, context_.RaisedError());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
XmlParser::~XmlParser() {
|
||||
XML_ParserFree(expat_);
|
||||
}
|
||||
|
||||
void
|
||||
XmlParser::ParseXml(XmlParseHandler *pxph, std::string text) {
|
||||
XmlParser parser(pxph);
|
||||
parser.Parse(text.c_str(), text.length(), true);
|
||||
}
|
||||
|
||||
XmlParser::ParseContext::ParseContext() :
|
||||
xmlnsstack_(),
|
||||
raised_(XML_ERROR_NONE),
|
||||
line_number_(0),
|
||||
column_number_(0),
|
||||
byte_index_(0) {
|
||||
}
|
||||
|
||||
void
|
||||
XmlParser::ParseContext::StartNamespace(const char *prefix, const char *ns) {
|
||||
xmlnsstack_.AddXmlns(*prefix ? prefix : STR_EMPTY, ns);
|
||||
}
|
||||
|
||||
void
|
||||
XmlParser::ParseContext::StartElement() {
|
||||
xmlnsstack_.PushFrame();
|
||||
}
|
||||
|
||||
void
|
||||
XmlParser::ParseContext::EndElement() {
|
||||
xmlnsstack_.PopFrame();
|
||||
}
|
||||
|
||||
QName
|
||||
XmlParser::ParseContext::ResolveQName(const char* qname, bool isAttr) {
|
||||
const char *c;
|
||||
for (c = qname; *c; ++c) {
|
||||
if (*c == ':') {
|
||||
const std::pair<std::string, bool> result =
|
||||
xmlnsstack_.NsForPrefix(std::string(qname, c - qname));
|
||||
if (!result.second)
|
||||
return QName();
|
||||
return QName(result.first, c + 1);
|
||||
}
|
||||
}
|
||||
if (isAttr)
|
||||
return QName(STR_EMPTY, qname);
|
||||
|
||||
std::pair<std::string, bool> result = xmlnsstack_.NsForPrefix(STR_EMPTY);
|
||||
if (!result.second)
|
||||
return QName();
|
||||
|
||||
return QName(result.first, qname);
|
||||
}
|
||||
|
||||
void
|
||||
XmlParser::ParseContext::Reset() {
|
||||
xmlnsstack_.Reset();
|
||||
raised_ = XML_ERROR_NONE;
|
||||
}
|
||||
|
||||
void
|
||||
XmlParser::ParseContext::SetPosition(int line, int column,
|
||||
long byte_index) {
|
||||
line_number_ = line;
|
||||
column_number_ = column;
|
||||
byte_index_ = byte_index;
|
||||
}
|
||||
|
||||
void
|
||||
XmlParser::ParseContext::GetPosition(unsigned long * line,
|
||||
unsigned long * column,
|
||||
unsigned long * byte_index) {
|
||||
if (line != NULL) {
|
||||
*line = static_cast<unsigned long>(line_number_);
|
||||
}
|
||||
|
||||
if (column != NULL) {
|
||||
*column = static_cast<unsigned long>(column_number_);
|
||||
}
|
||||
|
||||
if (byte_index != NULL) {
|
||||
*byte_index = static_cast<unsigned long>(byte_index_);
|
||||
}
|
||||
}
|
||||
|
||||
XmlParser::ParseContext::~ParseContext() {
|
||||
}
|
||||
|
||||
} // namespace buzz
|
@ -1,120 +0,0 @@
|
||||
/*
|
||||
* libjingle
|
||||
* Copyright 2004--2005, Google Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef TALK_XMLLITE_XMLPARSER_H_
|
||||
#define TALK_XMLLITE_XMLPARSER_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "talk/xmllite/xmlnsstack.h"
|
||||
#ifdef EXPAT_RELATIVE_PATH
|
||||
#include "expat.h"
|
||||
#else
|
||||
#include "third_party/expat/v2_0_1/Source/lib/expat.h"
|
||||
#endif // EXPAT_RELATIVE_PATH
|
||||
|
||||
struct XML_ParserStruct;
|
||||
typedef struct XML_ParserStruct* XML_Parser;
|
||||
|
||||
namespace buzz {
|
||||
|
||||
class XmlParseHandler;
|
||||
class XmlParseContext;
|
||||
class XmlParser;
|
||||
|
||||
class XmlParseContext {
|
||||
public:
|
||||
virtual ~XmlParseContext() {}
|
||||
virtual QName ResolveQName(const char * qname, bool isAttr) = 0;
|
||||
virtual void RaiseError(XML_Error err) = 0;
|
||||
virtual void GetPosition(unsigned long * line, unsigned long * column,
|
||||
unsigned long * byte_index) = 0;
|
||||
};
|
||||
|
||||
class XmlParseHandler {
|
||||
public:
|
||||
virtual ~XmlParseHandler() {}
|
||||
virtual void StartElement(XmlParseContext * pctx,
|
||||
const char * name, const char ** atts) = 0;
|
||||
virtual void EndElement(XmlParseContext * pctx,
|
||||
const char * name) = 0;
|
||||
virtual void CharacterData(XmlParseContext * pctx,
|
||||
const char * text, int len) = 0;
|
||||
virtual void Error(XmlParseContext * pctx,
|
||||
XML_Error errorCode) = 0;
|
||||
};
|
||||
|
||||
class XmlParser {
|
||||
public:
|
||||
static void ParseXml(XmlParseHandler * pxph, std::string text);
|
||||
|
||||
explicit XmlParser(XmlParseHandler * pxph);
|
||||
bool Parse(const char * data, size_t len, bool isFinal);
|
||||
void Reset();
|
||||
virtual ~XmlParser();
|
||||
|
||||
// expat callbacks
|
||||
void ExpatStartElement(const char * name, const char ** atts);
|
||||
void ExpatEndElement(const char * name);
|
||||
void ExpatCharacterData(const char * text, int len);
|
||||
void ExpatXmlDecl(const char * ver, const char * enc, int standalone);
|
||||
|
||||
private:
|
||||
|
||||
class ParseContext : public XmlParseContext {
|
||||
public:
|
||||
ParseContext();
|
||||
virtual ~ParseContext();
|
||||
virtual QName ResolveQName(const char * qname, bool isAttr);
|
||||
virtual void RaiseError(XML_Error err) { if (!raised_) raised_ = err; }
|
||||
virtual void GetPosition(unsigned long * line, unsigned long * column,
|
||||
unsigned long * byte_index);
|
||||
XML_Error RaisedError() { return raised_; }
|
||||
void Reset();
|
||||
|
||||
void StartElement();
|
||||
void EndElement();
|
||||
void StartNamespace(const char * prefix, const char * ns);
|
||||
void SetPosition(int line, int column, long byte_index);
|
||||
|
||||
private:
|
||||
XmlnsStack xmlnsstack_;
|
||||
XML_Error raised_;
|
||||
XML_Size line_number_;
|
||||
XML_Size column_number_;
|
||||
XML_Index byte_index_;
|
||||
};
|
||||
|
||||
ParseContext context_;
|
||||
XML_Parser expat_;
|
||||
XmlParseHandler * pxph_;
|
||||
bool sentError_;
|
||||
};
|
||||
|
||||
} // namespace buzz
|
||||
|
||||
#endif // TALK_XMLLITE_XMLPARSER_H_
|
@ -1,302 +0,0 @@
|
||||
/*
|
||||
* libjingle
|
||||
* Copyright 2004, Google Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include "talk/xmllite/qname.h"
|
||||
#include "talk/xmllite/xmlparser.h"
|
||||
#include "webrtc/base/common.h"
|
||||
#include "webrtc/base/gunit.h"
|
||||
|
||||
using buzz::QName;
|
||||
using buzz::XmlParser;
|
||||
using buzz::XmlParseContext;
|
||||
using buzz::XmlParseHandler;
|
||||
|
||||
class XmlParserTestHandler : public XmlParseHandler {
|
||||
public:
|
||||
virtual void StartElement(XmlParseContext * pctx,
|
||||
const char * name, const char ** atts) {
|
||||
ss_ << "START (" << pctx->ResolveQName(name, false).Merged();
|
||||
while (*atts) {
|
||||
ss_ << ", " << pctx->ResolveQName(*atts, true).Merged()
|
||||
<< "='" << *(atts+1) << "'";
|
||||
atts += 2;
|
||||
}
|
||||
ss_ << ") ";
|
||||
}
|
||||
virtual void EndElement(XmlParseContext * pctx, const char * name) {
|
||||
RTC_UNUSED(pctx);
|
||||
RTC_UNUSED(name);
|
||||
ss_ << "END ";
|
||||
}
|
||||
virtual void CharacterData(XmlParseContext * pctx,
|
||||
const char * text, int len) {
|
||||
RTC_UNUSED(pctx);
|
||||
ss_ << "TEXT (" << std::string(text, len) << ") ";
|
||||
}
|
||||
virtual void Error(XmlParseContext * pctx, XML_Error code) {
|
||||
RTC_UNUSED(pctx);
|
||||
ss_ << "ERROR (" << static_cast<int>(code) << ") ";
|
||||
}
|
||||
virtual ~XmlParserTestHandler() {
|
||||
}
|
||||
|
||||
std::string Str() {
|
||||
return ss_.str();
|
||||
}
|
||||
|
||||
std::string StrClear() {
|
||||
std::string result = ss_.str();
|
||||
ss_.str("");
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
std::stringstream ss_;
|
||||
};
|
||||
|
||||
|
||||
TEST(XmlParserTest, TestTrivial) {
|
||||
XmlParserTestHandler handler;
|
||||
XmlParser::ParseXml(&handler, "<testing/>");
|
||||
EXPECT_EQ("START (testing) END ", handler.Str());
|
||||
}
|
||||
|
||||
TEST(XmlParserTest, TestAttributes) {
|
||||
{
|
||||
XmlParserTestHandler handler;
|
||||
XmlParser::ParseXml(&handler, "<testing a='b'/>");
|
||||
EXPECT_EQ("START (testing, a='b') END ", handler.Str());
|
||||
}
|
||||
{
|
||||
XmlParserTestHandler handler;
|
||||
XmlParser::ParseXml(&handler, "<testing e='' long='some text'/>");
|
||||
EXPECT_EQ("START (testing, e='', long='some text') END ", handler.Str());
|
||||
}
|
||||
}
|
||||
|
||||
TEST(XmlParserTest, TestNesting) {
|
||||
{
|
||||
XmlParserTestHandler handler;
|
||||
XmlParser::ParseXml(&handler,
|
||||
"<top><first/><second><third></third></second></top>");
|
||||
EXPECT_EQ("START (top) START (first) END START (second) START (third) "
|
||||
"END END END ", handler.Str());
|
||||
}
|
||||
{
|
||||
XmlParserTestHandler handler;
|
||||
XmlParser::ParseXml(&handler, "<top><fifth><deeper><and><deeper/></and>"
|
||||
"<sibling><leaf/></sibling></deeper></fifth><first/><second>"
|
||||
"<third></third></second></top>");
|
||||
EXPECT_EQ("START (top) START (fifth) START (deeper) START (and) START "
|
||||
"(deeper) END END START (sibling) START (leaf) END END END "
|
||||
"END START (first) END START (second) START (third) END END END ",
|
||||
handler.Str());
|
||||
}
|
||||
}
|
||||
|
||||
TEST(XmlParserTest, TestXmlDecl) {
|
||||
{
|
||||
XmlParserTestHandler handler;
|
||||
XmlParser::ParseXml(&handler, "<?xml version=\"1.0\"?><testing/>");
|
||||
EXPECT_EQ("START (testing) END ", handler.Str());
|
||||
}
|
||||
{
|
||||
XmlParserTestHandler handler;
|
||||
XmlParser::ParseXml(&handler,
|
||||
"<?xml version=\"1.0\" encoding=\"utf-8\"?><testing/>");
|
||||
EXPECT_EQ("START (testing) END ", handler.Str());
|
||||
}
|
||||
{
|
||||
XmlParserTestHandler handler;
|
||||
XmlParser::ParseXml(&handler,
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
|
||||
"<testing/>");
|
||||
EXPECT_EQ("START (testing) END ", handler.Str());
|
||||
}
|
||||
}
|
||||
|
||||
TEST(XmlParserTest, TestNamespace) {
|
||||
{
|
||||
XmlParserTestHandler handler;
|
||||
XmlParser::ParseXml(&handler, "<top xmlns='my-namespace' a='b'/>");
|
||||
EXPECT_EQ("START (my-namespace:top, xmlns='my-namespace', a='b') END ",
|
||||
handler.Str());
|
||||
}
|
||||
{
|
||||
XmlParserTestHandler handler;
|
||||
XmlParser::ParseXml(&handler, "<foo:top xmlns:foo='my-namespace' "
|
||||
"a='b' foo:c='d'/>");
|
||||
EXPECT_EQ("START (my-namespace:top, "
|
||||
"http://www.w3.org/2000/xmlns/:foo='my-namespace', "
|
||||
"a='b', my-namespace:c='d') END ", handler.Str());
|
||||
}
|
||||
{
|
||||
XmlParserTestHandler handler;
|
||||
XmlParser::ParseXml(&handler, "<top><nested xmlns='my-namespace'><leaf/>"
|
||||
"</nested><sibling/></top>");
|
||||
EXPECT_EQ("START (top) START (my-namespace:nested, xmlns='my-namespace') "
|
||||
"START (my-namespace:leaf) END END START (sibling) END END ",
|
||||
handler.Str());
|
||||
}
|
||||
}
|
||||
|
||||
TEST(XmlParserTest, TestIncremental) {
|
||||
XmlParserTestHandler handler;
|
||||
XmlParser parser(&handler);
|
||||
std::string fragment;
|
||||
|
||||
fragment = "<stream:stream";
|
||||
parser.Parse(fragment.c_str(), fragment.length(), false);
|
||||
EXPECT_EQ("", handler.StrClear());
|
||||
|
||||
fragment = " id=\"abcdefg\" xmlns=\"";
|
||||
parser.Parse(fragment.c_str(), fragment.length(), false);
|
||||
EXPECT_EQ("", handler.StrClear());
|
||||
|
||||
fragment = "j:c\" xmlns:stream='hm";
|
||||
parser.Parse(fragment.c_str(), fragment.length(), false);
|
||||
EXPECT_EQ("", handler.StrClear());
|
||||
|
||||
fragment = "ph'><test";
|
||||
parser.Parse(fragment.c_str(), fragment.length(), false);
|
||||
EXPECT_EQ("START (hmph:stream, id='abcdefg', xmlns='j:c', "
|
||||
"http://www.w3.org/2000/xmlns/:stream='hmph') ", handler.StrClear());
|
||||
|
||||
fragment = "ing/><again/>abracad";
|
||||
parser.Parse(fragment.c_str(), fragment.length(), false);
|
||||
EXPECT_EQ("START (j:c:testing) END START (j:c:again) END TEXT (abracad) ",
|
||||
handler.StrClear());
|
||||
|
||||
fragment = "abra</stream:";
|
||||
parser.Parse(fragment.c_str(), fragment.length(), false);
|
||||
EXPECT_EQ("TEXT (abra) ", handler.StrClear());
|
||||
|
||||
fragment = "stream>";
|
||||
parser.Parse(fragment.c_str(), fragment.length(), false);
|
||||
EXPECT_EQ("END ", handler.StrClear());
|
||||
}
|
||||
|
||||
TEST(XmlParserTest, TestReset) {
|
||||
{
|
||||
XmlParserTestHandler handler;
|
||||
XmlParser parser(&handler);
|
||||
std::string fragment;
|
||||
|
||||
fragment = "<top><first/><second><third></third>";
|
||||
parser.Parse(fragment.c_str(), fragment.length(), false);
|
||||
EXPECT_EQ("START (top) START (first) END START (second) START (third) END ",
|
||||
handler.StrClear());
|
||||
|
||||
parser.Reset();
|
||||
fragment = "<tip><first/><second><third></third>";
|
||||
parser.Parse(fragment.c_str(), fragment.length(), false);
|
||||
EXPECT_EQ("START (tip) START (first) END START (second) START (third) END ",
|
||||
handler.StrClear());
|
||||
}
|
||||
{
|
||||
XmlParserTestHandler handler;
|
||||
XmlParser parser(&handler);
|
||||
std::string fragment;
|
||||
|
||||
fragment = "<top xmlns='m'>";
|
||||
parser.Parse(fragment.c_str(), fragment.length(), false);
|
||||
EXPECT_EQ("START (m:top, xmlns='m') ", handler.StrClear());
|
||||
|
||||
fragment = "<testing/><frag";
|
||||
parser.Parse(fragment.c_str(), fragment.length(), false);
|
||||
EXPECT_EQ("START (m:testing) END ", handler.StrClear());
|
||||
|
||||
parser.Reset();
|
||||
fragment = "<testing><fragment/";
|
||||
parser.Parse(fragment.c_str(), fragment.length(), false);
|
||||
EXPECT_EQ("START (testing) ", handler.StrClear());
|
||||
|
||||
fragment = ">";
|
||||
parser.Parse(fragment.c_str(), fragment.length(), false);
|
||||
EXPECT_EQ("START (fragment) END ", handler.StrClear());
|
||||
}
|
||||
}
|
||||
|
||||
TEST(XmlParserTest, TestError) {
|
||||
{
|
||||
XmlParserTestHandler handler;
|
||||
XmlParser::ParseXml(&handler, "junk");
|
||||
EXPECT_EQ("ERROR (2) ", handler.Str());
|
||||
}
|
||||
{
|
||||
XmlParserTestHandler handler;
|
||||
XmlParser::ParseXml(&handler, "<top/> garbage ");
|
||||
EXPECT_EQ("START (top) END ERROR (9) ", handler.Str());
|
||||
}
|
||||
{
|
||||
XmlParserTestHandler handler;
|
||||
XmlParser::ParseXml(&handler, "<-hm->");
|
||||
EXPECT_EQ("ERROR (4) ", handler.Str());
|
||||
}
|
||||
{
|
||||
XmlParserTestHandler handler;
|
||||
XmlParser::ParseXml(&handler, "<hello>&foobar;</hello>");
|
||||
EXPECT_EQ("START (hello) ERROR (11) ", handler.Str());
|
||||
}
|
||||
{
|
||||
XmlParserTestHandler handler;
|
||||
XmlParser::ParseXml(&handler,
|
||||
"<!DOCTYPE HTML PUBLIC \"foobar\" \"barfoo\">");
|
||||
EXPECT_EQ("ERROR (3) ", handler.Str());
|
||||
}
|
||||
{
|
||||
// XmlParser requires utf-8
|
||||
XmlParserTestHandler handler;
|
||||
XmlParser::ParseXml(&handler,
|
||||
"<?xml version=\"1.0\" encoding=\"iso-8859-1\"?><test/>");
|
||||
EXPECT_EQ("ERROR (19) ", handler.Str());
|
||||
}
|
||||
{
|
||||
// XmlParser requires version 1.0
|
||||
XmlParserTestHandler handler;
|
||||
XmlParser::ParseXml(&handler,
|
||||
"<?xml version=\"2.0\"?><test/>");
|
||||
EXPECT_EQ("ERROR (2) ", handler.Str());
|
||||
}
|
||||
{
|
||||
// XmlParser requires standalone documents
|
||||
XmlParserTestHandler handler;
|
||||
XmlParser::ParseXml(&handler,
|
||||
"<?xml version=\"1.0\" standalone=\"no\"?><test/>");
|
||||
EXPECT_EQ("ERROR (2) ", handler.Str());
|
||||
}
|
||||
{
|
||||
// XmlParser doesn't like empty namespace URIs
|
||||
XmlParserTestHandler handler;
|
||||
XmlParser::ParseXml(&handler,
|
||||
"<test xmlns:foo='' foo:bar='huh?'>");
|
||||
EXPECT_EQ("ERROR (2) ", handler.Str());
|
||||
}
|
||||
}
|
@ -1,191 +0,0 @@
|
||||
/*
|
||||
* libjingle
|
||||
* Copyright 2004--2005, Google Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "talk/xmllite/xmlprinter.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "talk/xmllite/xmlconstants.h"
|
||||
#include "talk/xmllite/xmlelement.h"
|
||||
#include "talk/xmllite/xmlnsstack.h"
|
||||
|
||||
namespace buzz {
|
||||
|
||||
class XmlPrinterImpl {
|
||||
public:
|
||||
XmlPrinterImpl(std::ostream* pout, XmlnsStack* ns_stack);
|
||||
void PrintElement(const XmlElement* element);
|
||||
void PrintQuotedValue(const std::string& text);
|
||||
void PrintBodyText(const std::string& text);
|
||||
void PrintCDATAText(const std::string& text);
|
||||
|
||||
private:
|
||||
std::ostream *pout_;
|
||||
XmlnsStack* ns_stack_;
|
||||
};
|
||||
|
||||
void XmlPrinter::PrintXml(std::ostream* pout, const XmlElement* element) {
|
||||
XmlnsStack ns_stack;
|
||||
PrintXml(pout, element, &ns_stack);
|
||||
}
|
||||
|
||||
void XmlPrinter::PrintXml(std::ostream* pout, const XmlElement* element,
|
||||
XmlnsStack* ns_stack) {
|
||||
XmlPrinterImpl printer(pout, ns_stack);
|
||||
printer.PrintElement(element);
|
||||
}
|
||||
|
||||
XmlPrinterImpl::XmlPrinterImpl(std::ostream* pout, XmlnsStack* ns_stack)
|
||||
: pout_(pout),
|
||||
ns_stack_(ns_stack) {
|
||||
}
|
||||
|
||||
void XmlPrinterImpl::PrintElement(const XmlElement* element) {
|
||||
ns_stack_->PushFrame();
|
||||
|
||||
// first go through attrs of pel to add xmlns definitions
|
||||
const XmlAttr* attr;
|
||||
for (attr = element->FirstAttr(); attr; attr = attr->NextAttr()) {
|
||||
if (attr->Name() == QN_XMLNS) {
|
||||
ns_stack_->AddXmlns(STR_EMPTY, attr->Value());
|
||||
} else if (attr->Name().Namespace() == NS_XMLNS) {
|
||||
ns_stack_->AddXmlns(attr->Name().LocalPart(),
|
||||
attr->Value());
|
||||
}
|
||||
}
|
||||
|
||||
// then go through qnames to make sure needed xmlns definitons are added
|
||||
std::vector<std::string> new_ns;
|
||||
std::pair<std::string, bool> prefix;
|
||||
prefix = ns_stack_->AddNewPrefix(element->Name().Namespace(), false);
|
||||
if (prefix.second) {
|
||||
new_ns.push_back(prefix.first);
|
||||
new_ns.push_back(element->Name().Namespace());
|
||||
}
|
||||
|
||||
for (attr = element->FirstAttr(); attr; attr = attr->NextAttr()) {
|
||||
prefix = ns_stack_->AddNewPrefix(attr->Name().Namespace(), true);
|
||||
if (prefix.second) {
|
||||
new_ns.push_back(prefix.first);
|
||||
new_ns.push_back(attr->Name().Namespace());
|
||||
}
|
||||
}
|
||||
|
||||
// print the element name
|
||||
*pout_ << '<' << ns_stack_->FormatQName(element->Name(), false);
|
||||
|
||||
// and the attributes
|
||||
for (attr = element->FirstAttr(); attr; attr = attr->NextAttr()) {
|
||||
*pout_ << ' ' << ns_stack_->FormatQName(attr->Name(), true) << "=\"";
|
||||
PrintQuotedValue(attr->Value());
|
||||
*pout_ << '"';
|
||||
}
|
||||
|
||||
// and the extra xmlns declarations
|
||||
std::vector<std::string>::iterator i(new_ns.begin());
|
||||
while (i < new_ns.end()) {
|
||||
if (*i == STR_EMPTY) {
|
||||
*pout_ << " xmlns=\"" << *(i + 1) << '"';
|
||||
} else {
|
||||
*pout_ << " xmlns:" << *i << "=\"" << *(i + 1) << '"';
|
||||
}
|
||||
i += 2;
|
||||
}
|
||||
|
||||
// now the children
|
||||
const XmlChild* child = element->FirstChild();
|
||||
|
||||
if (child == NULL)
|
||||
*pout_ << "/>";
|
||||
else {
|
||||
*pout_ << '>';
|
||||
while (child) {
|
||||
if (child->IsText()) {
|
||||
if (element->IsCDATA()) {
|
||||
PrintCDATAText(child->AsText()->Text());
|
||||
} else {
|
||||
PrintBodyText(child->AsText()->Text());
|
||||
}
|
||||
} else {
|
||||
PrintElement(child->AsElement());
|
||||
}
|
||||
child = child->NextChild();
|
||||
}
|
||||
*pout_ << "</" << ns_stack_->FormatQName(element->Name(), false) << '>';
|
||||
}
|
||||
|
||||
ns_stack_->PopFrame();
|
||||
}
|
||||
|
||||
void XmlPrinterImpl::PrintQuotedValue(const std::string& text) {
|
||||
size_t safe = 0;
|
||||
for (;;) {
|
||||
size_t unsafe = text.find_first_of("<>&\"", safe);
|
||||
if (unsafe == std::string::npos)
|
||||
unsafe = text.length();
|
||||
*pout_ << text.substr(safe, unsafe - safe);
|
||||
if (unsafe == text.length())
|
||||
return;
|
||||
switch (text[unsafe]) {
|
||||
case '<': *pout_ << "<"; break;
|
||||
case '>': *pout_ << ">"; break;
|
||||
case '&': *pout_ << "&"; break;
|
||||
case '"': *pout_ << """; break;
|
||||
}
|
||||
safe = unsafe + 1;
|
||||
if (safe == text.length())
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void XmlPrinterImpl::PrintBodyText(const std::string& text) {
|
||||
size_t safe = 0;
|
||||
for (;;) {
|
||||
size_t unsafe = text.find_first_of("<>&", safe);
|
||||
if (unsafe == std::string::npos)
|
||||
unsafe = text.length();
|
||||
*pout_ << text.substr(safe, unsafe - safe);
|
||||
if (unsafe == text.length())
|
||||
return;
|
||||
switch (text[unsafe]) {
|
||||
case '<': *pout_ << "<"; break;
|
||||
case '>': *pout_ << ">"; break;
|
||||
case '&': *pout_ << "&"; break;
|
||||
}
|
||||
safe = unsafe + 1;
|
||||
if (safe == text.length())
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void XmlPrinterImpl::PrintCDATAText(const std::string& text) {
|
||||
*pout_ << "<![CDATA[" << text << "]]>";
|
||||
}
|
||||
|
||||
} // namespace buzz
|
@ -1,49 +0,0 @@
|
||||
/*
|
||||
* libjingle
|
||||
* Copyright 2004--2005, Google Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef TALK_XMLLITE_XMLPRINTER_H_
|
||||
#define TALK_XMLLITE_XMLPRINTER_H_
|
||||
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
|
||||
namespace buzz {
|
||||
|
||||
class XmlElement;
|
||||
class XmlnsStack;
|
||||
|
||||
class XmlPrinter {
|
||||
public:
|
||||
static void PrintXml(std::ostream* pout, const XmlElement* pelt);
|
||||
|
||||
static void PrintXml(std::ostream* pout, const XmlElement* pelt,
|
||||
XmlnsStack* ns_stack);
|
||||
};
|
||||
|
||||
} // namespace buzz
|
||||
|
||||
#endif // TALK_XMLLITE_XMLPRINTER_H_
|
@ -1,62 +0,0 @@
|
||||
/*
|
||||
* libjingle
|
||||
* Copyright 2004, Google Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "talk/xmllite/xmlprinter.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "talk/xmllite/qname.h"
|
||||
#include "talk/xmllite/xmlelement.h"
|
||||
#include "talk/xmllite/xmlnsstack.h"
|
||||
#include "webrtc/base/common.h"
|
||||
#include "webrtc/base/gunit.h"
|
||||
|
||||
using buzz::QName;
|
||||
using buzz::XmlElement;
|
||||
using buzz::XmlnsStack;
|
||||
using buzz::XmlPrinter;
|
||||
|
||||
TEST(XmlPrinterTest, TestBasicPrinting) {
|
||||
XmlElement elt(QName("google:test", "first"));
|
||||
std::stringstream ss;
|
||||
XmlPrinter::PrintXml(&ss, &elt);
|
||||
EXPECT_EQ("<test:first xmlns:test=\"google:test\"/>", ss.str());
|
||||
}
|
||||
|
||||
TEST(XmlPrinterTest, TestNamespacedPrinting) {
|
||||
XmlElement elt(QName("google:test", "first"));
|
||||
elt.AddElement(new XmlElement(QName("nested:test", "second")));
|
||||
std::stringstream ss;
|
||||
|
||||
XmlnsStack ns_stack;
|
||||
ns_stack.AddXmlns("gg", "google:test");
|
||||
ns_stack.AddXmlns("", "nested:test");
|
||||
|
||||
XmlPrinter::PrintXml(&ss, &elt, &ns_stack);
|
||||
EXPECT_EQ("<gg:first><second/></gg:first>", ss.str());
|
||||
}
|
Loading…
Reference in New Issue
Block a user