Expose XML parsing support (issue #28).

git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@119 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
Marshall Greenblatt 2010-10-20 15:12:46 +00:00
parent 4c0ccb6768
commit 18bc093786
15 changed files with 3116 additions and 2 deletions

11
cef.gyp
View File

@ -98,6 +98,7 @@
'tests/unittests/test_handler.h', 'tests/unittests/test_handler.h',
'tests/unittests/test_suite.h', 'tests/unittests/test_suite.h',
'tests/unittests/v8_unittest.cc', 'tests/unittests/v8_unittest.cc',
'tests/unittests/xml_reader_unittest.cc',
], ],
'include_dirs': [ 'include_dirs': [
'.', '.',
@ -157,6 +158,7 @@
'../third_party/icu/icu.gyp:icuuc', '../third_party/icu/icu.gyp:icuuc',
'../third_party/libjpeg/libjpeg.gyp:libjpeg', '../third_party/libjpeg/libjpeg.gyp:libjpeg',
'../third_party/libpng/libpng.gyp:libpng', '../third_party/libpng/libpng.gyp:libpng',
'../third_party/libxml/libxml.gyp:libxml',
'../third_party/libxslt/libxslt.gyp:libxslt', '../third_party/libxslt/libxslt.gyp:libxslt',
'../third_party/mesa/mesa.gyp:osmesa', '../third_party/mesa/mesa.gyp:osmesa',
'../third_party/modp_b64/modp_b64.gyp:modp_b64', '../third_party/modp_b64/modp_b64.gyp:modp_b64',
@ -216,6 +218,8 @@
'libcef_dll/cpptoc/stream_writer_cpptoc.h', 'libcef_dll/cpptoc/stream_writer_cpptoc.h',
'libcef_dll/cpptoc/v8value_cpptoc.cc', 'libcef_dll/cpptoc/v8value_cpptoc.cc',
'libcef_dll/cpptoc/v8value_cpptoc.h', 'libcef_dll/cpptoc/v8value_cpptoc.h',
'libcef_dll/cpptoc/xml_reader_cpptoc.cc',
'libcef_dll/cpptoc/xml_reader_cpptoc.h',
'libcef_dll/ctocpp/ctocpp.h', 'libcef_dll/ctocpp/ctocpp.h',
'libcef_dll/ctocpp/download_handler_ctocpp.cc', 'libcef_dll/ctocpp/download_handler_ctocpp.cc',
'libcef_dll/ctocpp/download_handler_ctocpp.h', 'libcef_dll/ctocpp/download_handler_ctocpp.h',
@ -274,6 +278,7 @@
'..', '..',
], ],
'sources': [ 'sources': [
'include/cef_wrapper.h',
'libcef_dll/cef_logging.h', 'libcef_dll/cef_logging.h',
'libcef_dll/cpptoc/cpptoc.h', 'libcef_dll/cpptoc/cpptoc.h',
'libcef_dll/cpptoc/download_handler_cpptoc.cc', 'libcef_dll/cpptoc/download_handler_cpptoc.cc',
@ -309,8 +314,11 @@
'libcef_dll/cpptoc/task_cpptoc.h', 'libcef_dll/cpptoc/task_cpptoc.h',
'libcef_dll/ctocpp/v8value_ctocpp.cc', 'libcef_dll/ctocpp/v8value_ctocpp.cc',
'libcef_dll/ctocpp/v8value_ctocpp.h', 'libcef_dll/ctocpp/v8value_ctocpp.h',
'libcef_dll/ctocpp/xml_reader_ctocpp.cc',
'libcef_dll/ctocpp/xml_reader_ctocpp.h',
'libcef_dll/transfer_util.cpp', 'libcef_dll/transfer_util.cpp',
'libcef_dll/transfer_util.h', 'libcef_dll/transfer_util.h',
'libcef_dll/wrapper/cef_xml_object.cc',
'libcef_dll/wrapper/libcef_dll_wrapper.cc', 'libcef_dll/wrapper/libcef_dll_wrapper.cc',
], ],
}, },
@ -344,6 +352,7 @@
'../third_party/icu/icu.gyp:icuuc', '../third_party/icu/icu.gyp:icuuc',
'../third_party/libjpeg/libjpeg.gyp:libjpeg', '../third_party/libjpeg/libjpeg.gyp:libjpeg',
'../third_party/libpng/libpng.gyp:libpng', '../third_party/libpng/libpng.gyp:libpng',
'../third_party/libxml/libxml.gyp:libxml',
'../third_party/libxslt/libxslt.gyp:libxslt', '../third_party/libxslt/libxslt.gyp:libxslt',
'../third_party/mesa/mesa.gyp:osmesa', '../third_party/mesa/mesa.gyp:osmesa',
'../third_party/modp_b64/modp_b64.gyp:modp_b64', '../third_party/modp_b64/modp_b64.gyp:modp_b64',
@ -423,6 +432,8 @@
'libcef/v8_impl.h', 'libcef/v8_impl.h',
'libcef/webview_host.h', 'libcef/webview_host.h',
'libcef/webwidget_host.h', 'libcef/webwidget_host.h',
'libcef/xml_reader_impl.cc',
'libcef/xml_reader_impl.h',
], ],
'conditions': [ 'conditions': [
['OS=="win"', { ['OS=="win"', {

View File

@ -265,6 +265,24 @@ public:
void Lock() { m_critsec.Lock(); } void Lock() { m_critsec.Lock(); }
void Unlock() { m_critsec.Unlock(); } void Unlock() { m_critsec.Unlock(); }
// A helper class that acquires the lock for the given CefThreadSafeBase while
// the CefAutoLock is in scope.
class AutoLock
{
public:
AutoLock(CefThreadSafeBase* base) : base_(base)
{
base_->Lock();
}
~AutoLock()
{
base_->Unlock();
}
private:
CefThreadSafeBase* base_;
};
protected: protected:
long m_dwRef; long m_dwRef;
CefCriticalSection m_critsec; CefCriticalSection m_critsec;
@ -1005,7 +1023,7 @@ public:
class CefStreamWriter : public CefBase class CefStreamWriter : public CefBase
{ {
public: public:
// Create a new CefStreamWriter object. // Create a new CefStreamWriter object.
/*--cef()--*/ /*--cef()--*/
static CefRefPtr<CefStreamWriter> CreateForFile(const std::wstring& fileName); static CefRefPtr<CefStreamWriter> CreateForFile(const std::wstring& fileName);
/*--cef()--*/ /*--cef()--*/
@ -1232,4 +1250,166 @@ public:
virtual void Complete() =0; virtual void Complete() =0;
}; };
// Class that supports the reading of XML data via the libxml streaming API.
/*--cef(source=library)--*/
class CefXmlReader : public CefBase
{
public:
typedef cef_xml_encoding_type_t EncodingType;
typedef cef_xml_node_type_t NodeType;
// Create a new CefXmlReader object. The returned object's methods can only
// be called from the thread that created the object.
/*--cef()--*/
static CefRefPtr<CefXmlReader> Create(CefRefPtr<CefStreamReader> stream,
EncodingType encodingType,
const std::wstring& URI);
// Moves the cursor to the next element node in the document. This method
// must be called at least once to set the current cursor position. Returns
// true if the cursor position was set successfully.
/*--cef()--*/
virtual bool MoveToNextElement() =0;
// Close the document. This must be called directly to ensure that cleanup
// occurs on the correct thread.
/*--cef()--*/
virtual bool Close() =0;
// Returns true if an error has been reported by the XML parser.
/*--cef()--*/
virtual bool HasError() =0;
// Returns the error string.
/*--cef()--*/
virtual std::wstring GetError() =0;
// The below methods retrieve data for the node at the current cursor
// position.
// Returns the node type.
/*--cef()--*/
virtual NodeType GetType() =0;
// Returns the node depth. Depth starts at 0 for the root node.
/*--cef()--*/
virtual int GetDepth() =0;
// Returns the local name. See
// http://www.w3.org/TR/REC-xml-names/#NT-LocalPart for additional details.
/*--cef()--*/
virtual std::wstring GetLocalName() =0;
// Returns the namespace prefix. See http://www.w3.org/TR/REC-xml-names/ for
// additional details.
/*--cef()--*/
virtual std::wstring GetPrefix() =0;
// Returns the qualified name, equal to (Prefix:)LocalName. See
// http://www.w3.org/TR/REC-xml-names/#ns-qualnames for additional details.
/*--cef()--*/
virtual std::wstring GetQualifiedName() =0;
// Returns the URI defining the namespace associated with the node. See
// http://www.w3.org/TR/REC-xml-names/ for additional details.
/*--cef()--*/
virtual std::wstring GetNamespaceURI() =0;
// Returns the base URI of the node. See http://www.w3.org/TR/xmlbase/ for
// additional details.
/*--cef()--*/
virtual std::wstring GetBaseURI() =0;
// Returns the xml:lang scope within which the node resides. See
// http://www.w3.org/TR/REC-xml/#sec-lang-tag for additional details.
/*--cef()--*/
virtual std::wstring GetXmlLang() =0;
// Returns true if the node represents an empty element. <a/> is considered
// empty but <a></a> is not.
/*--cef()--*/
virtual bool IsEmptyElement() =0;
// Returns true if the node has a text value.
/*--cef()--*/
virtual bool HasValue() =0;
// Returns the text value.
/*--cef()--*/
virtual std::wstring GetValue() =0;
// Returns true if the node has attributes.
/*--cef()--*/
virtual bool HasAttributes() =0;
// Returns the number of attributes.
/*--cef()--*/
virtual size_t GetAttributeCount() =0;
// Returns the value of the attribute at the specified 0-based index.
/*--cef(capi_name=get_attribute_byindex)--*/
virtual std::wstring GetAttribute(int index) =0;
// Returns the value of the attribute with the specified qualified name.
/*--cef(capi_name=get_attribute_byqname)--*/
virtual std::wstring GetAttribute(const std::wstring& qualifiedName) =0;
// Returns the value of the attribute with the specified local name and
// namespace URI.
/*--cef(capi_name=get_attribute_bylname)--*/
virtual std::wstring GetAttribute(const std::wstring& localName,
const std::wstring& namespaceURI) =0;
// Returns an XML representation of the current node's children.
/*--cef()--*/
virtual std::wstring GetInnerXml() =0;
// Returns an XML representation of the current node including its children.
/*--cef()--*/
virtual std::wstring GetOuterXml() =0;
// Returns the line number for the current node.
/*--cef()--*/
virtual int GetLineNumber() =0;
// Attribute nodes are not traversed by default. The below methods can be
// used to move the cursor to an attribute node. MoveToCarryingElement() can
// be called afterwards to return the cursor to the carrying element. The
// depth of an attribute node will be 1 + the depth of the carrying element.
// Moves the cursor to the attribute at the specified 0-based index. Returns
// true if the cursor position was set successfully.
/*--cef(capi_name=move_to_attribute_byindex)--*/
virtual bool MoveToAttribute(int index) =0;
// Moves the cursor to the attribute with the specified qualified name.
// Returns true if the cursor position was set successfully.
/*--cef(capi_name=move_to_attribute_byqname)--*/
virtual bool MoveToAttribute(const std::wstring& qualifiedName) =0;
// Moves the cursor to the attribute with the specified local name and
// namespace URI. Returns true if the cursor position was set successfully.
/*--cef(capi_name=move_to_attribute_bylname)--*/
virtual bool MoveToAttribute(const std::wstring& localName,
const std::wstring& namespaceURI) =0;
// Moves the cursor to the first attribute in the current element. Returns
// true if the cursor position was set successfully.
/*--cef()--*/
virtual bool MoveToFirstAttribute() =0;
// Moves the cursor to the next attribute in the current element. Returns
// true if the cursor position was set successfully.
/*--cef()--*/
virtual bool MoveToNextAttribute() =0;
// Moves the cursor back to the carrying element. Returns true if the cursor
// position was set successfully.
/*--cef()--*/
virtual bool MoveToCarryingElement() =0;
};
#endif // _CEF_H #endif // _CEF_H

View File

@ -1004,6 +1004,159 @@ typedef struct _cef_download_handler_t
} cef_download_handler_t; } cef_download_handler_t;
// Structure that supports the reading of XML data via the libxml streaming API.
typedef struct _cef_xml_reader_t
{
// Base structure.
cef_base_t base;
// Moves the cursor to the next element node in the document. This function
// must be called at least once to set the current cursor position. Returns
// true (1) if the cursor position was set successfully.
int (CEF_CALLBACK *move_to_next_element)(struct _cef_xml_reader_t* self);
// Close the document. This must be called directly to ensure that cleanup
// occurs on the correct thread.
int (CEF_CALLBACK *close)(struct _cef_xml_reader_t* self);
// Returns true (1) if an error has been reported by the XML parser.
int (CEF_CALLBACK *has_error)(struct _cef_xml_reader_t* self);
// Returns the error string.
// The resulting string must be freed by calling cef_string_free().
cef_string_t (CEF_CALLBACK *get_error)(struct _cef_xml_reader_t* self);
// The below functions retrieve data for the node at the current cursor
// position.
// Returns the node type.
enum cef_xml_node_type_t (CEF_CALLBACK *get_type)(
struct _cef_xml_reader_t* self);
// Returns the node depth. Depth starts at 0 for the root node.
int (CEF_CALLBACK *get_depth)(struct _cef_xml_reader_t* self);
// Returns the local name. See http://www.w3.org/TR/REC-xml-names/#NT-
// LocalPart for additional details.
// The resulting string must be freed by calling cef_string_free().
cef_string_t (CEF_CALLBACK *get_local_name)(struct _cef_xml_reader_t* self);
// Returns the namespace prefix. See http://www.w3.org/TR/REC-xml-names/ for
// additional details.
// The resulting string must be freed by calling cef_string_free().
cef_string_t (CEF_CALLBACK *get_prefix)(struct _cef_xml_reader_t* self);
// Returns the qualified name, equal to (Prefix:)LocalName. See
// http://www.w3.org/TR/REC-xml-names/#ns-qualnames for additional details.
// The resulting string must be freed by calling cef_string_free().
cef_string_t (CEF_CALLBACK *get_qualified_name)(
struct _cef_xml_reader_t* self);
// Returns the URI defining the namespace associated with the node. See
// http://www.w3.org/TR/REC-xml-names/ for additional details.
// The resulting string must be freed by calling cef_string_free().
cef_string_t (CEF_CALLBACK *get_namespace_uri)(
struct _cef_xml_reader_t* self);
// Returns the base URI of the node. See http://www.w3.org/TR/xmlbase/ for
// additional details.
// The resulting string must be freed by calling cef_string_free().
cef_string_t (CEF_CALLBACK *get_base_uri)(struct _cef_xml_reader_t* self);
// Returns the xml:lang scope within which the node resides. See
// http://www.w3.org/TR/REC-xml/#sec-lang-tag for additional details.
// The resulting string must be freed by calling cef_string_free().
cef_string_t (CEF_CALLBACK *get_xml_lang)(struct _cef_xml_reader_t* self);
// Returns true (1) if the node represents an NULL element. <a/> is considered
// NULL but <a></a> is not.
int (CEF_CALLBACK *is_empty_element)(struct _cef_xml_reader_t* self);
// Returns true (1) if the node has a text value.
int (CEF_CALLBACK *has_value)(struct _cef_xml_reader_t* self);
// Returns the text value.
// The resulting string must be freed by calling cef_string_free().
cef_string_t (CEF_CALLBACK *get_value)(struct _cef_xml_reader_t* self);
// Returns true (1) if the node has attributes.
int (CEF_CALLBACK *has_attributes)(struct _cef_xml_reader_t* self);
// Returns the number of attributes.
size_t (CEF_CALLBACK *get_attribute_count)(struct _cef_xml_reader_t* self);
// Returns the value of the attribute at the specified 0-based index.
// The resulting string must be freed by calling cef_string_free().
cef_string_t (CEF_CALLBACK *get_attribute_byindex)(
struct _cef_xml_reader_t* self, int index);
// Returns the value of the attribute with the specified qualified name.
// The resulting string must be freed by calling cef_string_free().
cef_string_t (CEF_CALLBACK *get_attribute_byqname)(
struct _cef_xml_reader_t* self, const wchar_t* qualifiedName);
// Returns the value of the attribute with the specified local name and
// namespace URI.
// The resulting string must be freed by calling cef_string_free().
cef_string_t (CEF_CALLBACK *get_attribute_bylname)(
struct _cef_xml_reader_t* self, const wchar_t* localName,
const wchar_t* namespaceURI);
// Returns an XML representation of the current node's children.
// The resulting string must be freed by calling cef_string_free().
cef_string_t (CEF_CALLBACK *get_inner_xml)(struct _cef_xml_reader_t* self);
// Returns an XML representation of the current node including its children.
// The resulting string must be freed by calling cef_string_free().
cef_string_t (CEF_CALLBACK *get_outer_xml)(struct _cef_xml_reader_t* self);
// Returns the line number for the current node.
int (CEF_CALLBACK *get_line_number)(struct _cef_xml_reader_t* self);
// Attribute nodes are not traversed by default. The below functions can be
// used to move the cursor to an attribute node. move_to_carrying_element()
// can be called afterwards to return the cursor to the carrying element. The
// depth of an attribute node will be 1 + the depth of the carrying element.
// Moves the cursor to the attribute at the specified 0-based index. Returns
// true (1) if the cursor position was set successfully.
int (CEF_CALLBACK *move_to_attribute_byindex)(struct _cef_xml_reader_t* self,
int index);
// Moves the cursor to the attribute with the specified qualified name.
// Returns true (1) if the cursor position was set successfully.
int (CEF_CALLBACK *move_to_attribute_byqname)(struct _cef_xml_reader_t* self,
const wchar_t* qualifiedName);
// Moves the cursor to the attribute with the specified local name and
// namespace URI. Returns true (1) if the cursor position was set
// successfully.
int (CEF_CALLBACK *move_to_attribute_bylname)(struct _cef_xml_reader_t* self,
const wchar_t* localName, const wchar_t* namespaceURI);
// Moves the cursor to the first attribute in the current element. Returns
// true (1) if the cursor position was set successfully.
int (CEF_CALLBACK *move_to_first_attribute)(struct _cef_xml_reader_t* self);
// Moves the cursor to the next attribute in the current element. Returns true
// (1) if the cursor position was set successfully.
int (CEF_CALLBACK *move_to_next_attribute)(struct _cef_xml_reader_t* self);
// Moves the cursor back to the carrying element. Returns true (1) if the
// cursor position was set successfully.
int (CEF_CALLBACK *move_to_carrying_element)(struct _cef_xml_reader_t* self);
} cef_xml_reader_t;
// Create a new cef_xml_reader_t object. The returned object's functions can
// only be called from the thread that created the object.
CEF_EXPORT cef_xml_reader_t* cef_xml_reader_create(cef_stream_reader_t* stream,
enum cef_xml_encoding_type_t encodingType, const wchar_t* URI);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -301,6 +301,35 @@ typedef struct _cef_print_options_t
struct cef_print_margins paper_margins; struct cef_print_margins paper_margins;
} cef_print_options_t; } cef_print_options_t;
// Supported XML encoding types. The parser supports ASCII, ISO-8859-1, and
// UTF16 (LE and BE) by default. All other types must be translated to UTF8
// before being passed to the parser. If a BOM is detected and the correct
// decoder is available then that decoder will be used automatically.
enum cef_xml_encoding_type_t
{
XML_ENCODING_NONE = 0,
XML_ENCODING_UTF8,
XML_ENCODING_UTF16LE,
XML_ENCODING_UTF16BE,
XML_ENCODING_ASCII,
};
// XML node types.
enum cef_xml_node_type_t
{
XML_NODE_UNSUPPORTED = 0,
XML_NODE_PROCESSING_INSTRUCTION,
XML_NODE_DOCUMENT_TYPE,
XML_NODE_ELEMENT_START,
XML_NODE_ELEMENT_END,
XML_NODE_ATTRIBUTE,
XML_NODE_TEXT,
XML_NODE_CDATA,
XML_NODE_ENTITY_REFERENCE,
XML_NODE_WHITESPACE,
XML_NODE_COMMENT,
};
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

152
include/cef_wrapper.h Normal file
View File

@ -0,0 +1,152 @@
// Copyright (c) 2010 Marshall A. Greenblatt. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * 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.
// * Neither the name of Google Inc. nor the name Chromium Embedded
// Framework nor the names of its contributors may be used to endorse
// or promote products derived from this software without specific prior
// written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "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 COPYRIGHT
// OWNER OR CONTRIBUTORS 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.
//
// ---------------------------------------------------------------------------
//
// The contents of this file are only available to applications that link
// against the libcef_dll_wrapper target.
//
#ifndef _CEF_WRAPPER_H
#define _CEF_WRAPPER_H
#include "cef.h"
#include <map>
#include <vector>
// Thread safe class for representing XML data as a structured object. This
// class should not be used with large XML documents because all data will be
// resident in memory at the same time. This implementation supports a
// restricted set of XML features:
// (1) Processing instructions, whitespace and comments are ignored.
// (2) Elements and attributes must always be referenced using the fully
// qualified name (ie, namespace:localname).
// (3) Empty elements (<a/>) and elements with zero-length values (<a></a>)
// are considered the same.
// (4) Element nodes are considered part of a value if:
// (a) The element node follows a non-element node at the same depth
// (see 5), or
// (b) The element node does not have a namespace and the parent node does.
// (5) Mixed node types at the same depth are combined into a single element
// value as follows:
// (a) All node values are concatenated to form a single string value.
// (b) Entity reference nodes are resolved to the corresponding entity
// value.
// (c) Element nodes are represented by their outer XML string.
class CefXmlObject : public CefThreadSafeBase<CefBase>
{
public:
typedef std::vector<CefRefPtr<CefXmlObject> > ObjectVector;
typedef std::map<std::wstring, std::wstring > AttributeMap;
// Create a new object with the specified name. An object name must always be
// at least one character long.
CefXmlObject(const std::wstring& name);
virtual ~CefXmlObject();
// Load the contents of the specified XML stream into this object. The
// existing children and attributes, if any, will first be cleared.
bool Load(CefRefPtr<CefStreamReader> stream,
CefXmlReader::EncodingType encodingType,
const std::wstring& URI, std::wstring* loadError);
// Set the name, children and attributes of this object to a duplicate of the
// specified object's contents. The existing children and attributes, if any,
// will first be cleared.
void Set(CefRefPtr<CefXmlObject> object);
// Append a duplicate of the children and attributes of the specified object
// to this object. If |overwriteAttributes| is true then any attributes in
// this object that also exist in the specified object will be overwritten
// with the new values. The name of this object is not changed.
void Append(CefRefPtr<CefXmlObject> object, bool overwriteAttributes);
// Return a new object with the same name, children and attributes as this
// object. The parent of the new object will be NULL.
CefRefPtr<CefXmlObject> Duplicate();
// Clears this object's children and attributes. The name and parenting of
// this object are not changed.
void Clear();
// Access the object's name. An object name must always be at least one
// character long.
std::wstring GetName();
bool SetName(const std::wstring& name);
// Access the object's parent. The parent can be NULL if this object has not
// been added as the child on another object.
bool HasParent();
CefRefPtr<CefXmlObject> GetParent();
// Access the object's value. An object cannot have a value if it also has
// children. Attempting to set the value while children exist will fail.
bool HasValue();
std::wstring GetValue();
bool SetValue(const std::wstring& value);
// Access the object's attributes. Attributes must have unique names.
bool HasAttributes();
size_t GetAttributeCount();
bool HasAttribute(const std::wstring& name);
std::wstring GetAttributeValue(const std::wstring& name);
bool SetAttributeValue(const std::wstring& name, const std::wstring& value);
size_t GetAttributes(AttributeMap& attributes);
void ClearAttributes();
// Access the object's children. Each object can only have one parent so
// attempting to add an object that already has a parent will fail. Removing a
// child will set the child's parent to NULL. Adding a child will set the
// child's parent to this object. This object's value, if any, will be cleared
// if a child is added.
bool HasChildren();
size_t GetChildCount();
bool HasChild(CefRefPtr<CefXmlObject> child);
bool AddChild(CefRefPtr<CefXmlObject> child);
bool RemoveChild(CefRefPtr<CefXmlObject> child);
size_t GetChildren(ObjectVector& children);
void ClearChildren();
// Find the first child with the specified name.
CefRefPtr<CefXmlObject> FindChild(const std::wstring& name);
// Find all children with the specified name.
size_t FindChildren(const std::wstring& name, ObjectVector& children);
private:
void SetParent(CefXmlObject* parent);
std::wstring name_;
CefXmlObject* parent_;
std::wstring value_;
AttributeMap attributes_;
ObjectVector children_;
};
#endif // _CEF_WRAPPER_H

506
libcef/xml_reader_impl.cc Normal file
View File

@ -0,0 +1,506 @@
// Copyright (c) 20010 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#include "xml_reader_impl.h"
#include "base/logging.h"
#include "base/utf_string_conversions.h"
// Static functions
//static
CefRefPtr<CefXmlReader> CefXmlReader::Create(CefRefPtr<CefStreamReader> stream,
EncodingType encodingType,
const std::wstring& URI)
{
CefRefPtr<CefXmlReaderImpl> impl(new CefXmlReaderImpl());
if (!impl->Initialize(stream, encodingType, URI))
return NULL;
return impl.get();
}
// CefXmlReaderImpl
namespace {
/**
* xmlInputReadCallback:
* @context: an Input context
* @buffer: the buffer to store data read
* @len: the length of the buffer in bytes
*
* Callback used in the I/O Input API to read the resource
*
* Returns the number of bytes read or -1 in case of error
*/
int XMLCALL xml_read_callback(void * context, char * buffer, int len)
{
CefRefPtr<CefStreamReader> reader(static_cast<CefStreamReader*>(context));
return reader->Read(buffer, 1, len);
}
/**
* xmlInputCloseCallback:
* @context: an Input context
*
* Callback used in the I/O Input API to close the resource
*
* Returns 0 or -1 in case of error
*/
int XMLCALL xml_close_callback(void * context)
{
CefRefPtr<CefStreamReader> reader(static_cast<CefStreamReader*>(context));
// Release the reference added by CefXmlReaderImpl::Initialize().
reader->Release();
return 1;
}
/**
* xmlTextReaderErrorFunc:
* @arg: the user argument
* @msg: the message
* @severity: the severity of the error
* @locator: a locator indicating where the error occured
*
* Signature of an error callback from a reader parser
*/
void XMLCALL xml_error_callback(void *arg, const char *msg,
xmlParserSeverities severity, xmlTextReaderLocatorPtr locator)
{
if (!msg)
return;
std::wstring error_str;
UTF8ToWide(msg, strlen(msg), &error_str);
if (!error_str.empty() && error_str[error_str.length()-1] == '\n')
error_str.resize(error_str.length()-1);
std::wstringstream ss;
ss << error_str << L", line " << xmlTextReaderLocatorLineNumber(locator);
LOG(INFO) << ss.str();
CefRefPtr<CefXmlReaderImpl> impl(static_cast<CefXmlReaderImpl*>(arg));
impl->AppendError(ss.str());
}
/**
* xmlStructuredErrorFunc:
* @userData: user provided data for the error callback
* @error: the error being raised.
*
* Signature of the function to use when there is an error and
* the module handles the new error reporting mechanism.
*/
void XMLCALL xml_structured_error_callback(void *userData, xmlErrorPtr error)
{
if (!error->message)
return;
std::wstring error_str;
UTF8ToWide(error->message, strlen(error->message), &error_str);
if (!error_str.empty() && error_str[error_str.length()-1] == '\n')
error_str.resize(error_str.length()-1);
std::wstringstream ss;
ss << error_str << L", line " << error->line;
LOG(INFO) << ss.str();
CefRefPtr<CefXmlReaderImpl> impl(static_cast<CefXmlReaderImpl*>(userData));
impl->AppendError(ss.str());
}
std::wstring xmlCharToWString(const xmlChar* xmlStr, bool free)
{
if (!xmlStr)
return std::wstring();
const char* str = reinterpret_cast<const char*>(xmlStr);
std::wstring wstr;
UTF8ToWide(str, strlen(str), &wstr);
if (free)
xmlFree(const_cast<xmlChar*>(xmlStr));
return wstr;
}
} // namespace
CefXmlReaderImpl::CefXmlReaderImpl()
: supported_thread_id_(PlatformThread::CurrentId()), reader_(NULL)
{
}
CefXmlReaderImpl::~CefXmlReaderImpl()
{
if (reader_ != NULL) {
if (!VerifyContext()) {
// Close() is supposed to be called directly. We'll try to free the reader
// now on the wrong thread but there's no guarantee this call won't crash.
xmlFreeTextReader(reader_);
} else {
Close();
}
}
}
bool CefXmlReaderImpl::Initialize(CefRefPtr<CefStreamReader> stream,
EncodingType encodingType,
const std::wstring& URI)
{
xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
switch (encodingType) {
case XML_ENCODING_UTF8:
enc = XML_CHAR_ENCODING_UTF8;
break;
case XML_ENCODING_UTF16LE:
enc = XML_CHAR_ENCODING_UTF16LE;
break;
case XML_ENCODING_UTF16BE:
enc = XML_CHAR_ENCODING_UTF16BE;
break;
case XML_ENCODING_ASCII:
enc = XML_CHAR_ENCODING_ASCII;
break;
default:
break;
}
// Create the input buffer.
xmlParserInputBufferPtr input_buffer = xmlAllocParserInputBuffer(enc);
if (!input_buffer)
return false;
// Add a reference that will be released by xml_close_callback().
stream->AddRef();
input_buffer->context = stream.get();
input_buffer->readcallback = xml_read_callback;
input_buffer->closecallback = xml_close_callback;
// Create the text reader.
reader_ = xmlNewTextReader(input_buffer, WideToUTF8(URI).c_str());
if (!reader_) {
// Free the input buffer.
xmlFreeParserInputBuffer(input_buffer);
return false;
}
// Register the error callbacks.
xmlTextReaderSetErrorHandler(reader_, xml_error_callback, this);
xmlTextReaderSetStructuredErrorHandler(reader_,
xml_structured_error_callback, this);
return true;
}
bool CefXmlReaderImpl::MoveToNextElement()
{
if (!VerifyContext())
return false;
return xmlTextReaderRead(reader_) == 1 ? true : false;
}
bool CefXmlReaderImpl::Close()
{
if (!VerifyContext())
return false;
// The input buffer will be freed automatically.
xmlFreeTextReader(reader_);
reader_ = NULL;
return true;
}
bool CefXmlReaderImpl::HasError()
{
if (!VerifyContext())
return false;
return !error_buf_.str().empty();
}
std::wstring CefXmlReaderImpl::GetError()
{
if (!VerifyContext())
return std::wstring();
return error_buf_.str();
}
CefXmlReader::NodeType CefXmlReaderImpl::GetType()
{
if (!VerifyContext())
return XML_NODE_UNSUPPORTED;
switch (xmlTextReaderNodeType(reader_)) {
case XML_READER_TYPE_ELEMENT:
return XML_NODE_ELEMENT_START;
case XML_READER_TYPE_END_ELEMENT:
return XML_NODE_ELEMENT_END;
case XML_READER_TYPE_ATTRIBUTE:
return XML_NODE_ATTRIBUTE;
case XML_READER_TYPE_TEXT:
return XML_NODE_TEXT;
case XML_READER_TYPE_SIGNIFICANT_WHITESPACE:
case XML_READER_TYPE_WHITESPACE:
return XML_NODE_WHITESPACE;
case XML_READER_TYPE_CDATA:
return XML_NODE_CDATA;
case XML_READER_TYPE_ENTITY_REFERENCE:
return XML_NODE_ENTITY_REFERENCE;
case XML_READER_TYPE_PROCESSING_INSTRUCTION:
return XML_NODE_PROCESSING_INSTRUCTION;
case XML_READER_TYPE_COMMENT:
return XML_NODE_COMMENT;
case XML_READER_TYPE_DOCUMENT_TYPE:
return XML_NODE_DOCUMENT_TYPE;
default:
break;
}
return XML_NODE_UNSUPPORTED;
}
int CefXmlReaderImpl::GetDepth()
{
if (!VerifyContext())
return -1;
return xmlTextReaderDepth(reader_);
}
std::wstring CefXmlReaderImpl::GetLocalName()
{
if (!VerifyContext())
return std::wstring();
return xmlCharToWString(xmlTextReaderConstLocalName(reader_), false);
}
std::wstring CefXmlReaderImpl::GetPrefix()
{
if (!VerifyContext())
return std::wstring();
return xmlCharToWString(xmlTextReaderConstPrefix(reader_), false);
}
std::wstring CefXmlReaderImpl::GetQualifiedName()
{
if (!VerifyContext())
return std::wstring();
return xmlCharToWString(xmlTextReaderConstName(reader_), false);
}
std::wstring CefXmlReaderImpl::GetNamespaceURI()
{
if (!VerifyContext())
return std::wstring();
return xmlCharToWString(xmlTextReaderConstNamespaceUri(reader_), false);
}
std::wstring CefXmlReaderImpl::GetBaseURI()
{
if (!VerifyContext())
return std::wstring();
return xmlCharToWString(xmlTextReaderConstBaseUri(reader_), false);
}
std::wstring CefXmlReaderImpl::GetXmlLang()
{
if (!VerifyContext())
return std::wstring();
return xmlCharToWString(xmlTextReaderConstXmlLang(reader_), false);
}
bool CefXmlReaderImpl::IsEmptyElement()
{
if (!VerifyContext())
return false;
return xmlTextReaderIsEmptyElement(reader_) == 1 ? true : false;
}
bool CefXmlReaderImpl::HasValue()
{
if (!VerifyContext())
return false;
if (xmlTextReaderNodeType(reader_) == XML_READER_TYPE_ENTITY_REFERENCE) {
// Provide special handling to return entity reference values.
return true;
} else {
return xmlTextReaderHasValue(reader_) == 1 ? true : false;
}
}
std::wstring CefXmlReaderImpl::GetValue()
{
if (!VerifyContext())
return std::wstring();
if (xmlTextReaderNodeType(reader_) == XML_READER_TYPE_ENTITY_REFERENCE) {
// Provide special handling to return entity reference values.
xmlNodePtr node = xmlTextReaderCurrentNode(reader_);
if (node->content != NULL)
return xmlCharToWString(node->content, false);
return NULL;
} else {
return xmlCharToWString(xmlTextReaderConstValue(reader_), false);
}
}
bool CefXmlReaderImpl::HasAttributes()
{
if (!VerifyContext())
return false;
return xmlTextReaderHasAttributes(reader_) == 1 ? true : false;
}
size_t CefXmlReaderImpl::GetAttributeCount()
{
if (!VerifyContext())
return 0;
return xmlTextReaderAttributeCount(reader_);
}
std::wstring CefXmlReaderImpl::GetAttribute(int index)
{
if (!VerifyContext())
return std::wstring();
return xmlCharToWString(xmlTextReaderGetAttributeNo(reader_, index), true);
}
std::wstring CefXmlReaderImpl::GetAttribute(const std::wstring& qualifiedName)
{
if (!VerifyContext())
return std::wstring();
std::string qualifiedNameStr = WideToUTF8(qualifiedName);
return xmlCharToWString(xmlTextReaderGetAttribute(reader_,
BAD_CAST qualifiedNameStr.c_str()), true);
}
std::wstring CefXmlReaderImpl::GetAttribute(const std::wstring& localName,
const std::wstring& namespaceURI)
{
if (!VerifyContext())
return std::wstring();
std::string localNameStr = WideToUTF8(localName);
std::string namespaceURIStr = WideToUTF8(namespaceURI);
return xmlCharToWString(xmlTextReaderGetAttributeNs(reader_,
BAD_CAST localNameStr.c_str(), BAD_CAST namespaceURIStr.c_str()), true);
}
std::wstring CefXmlReaderImpl::GetInnerXml()
{
if (!VerifyContext())
return std::wstring();
return xmlCharToWString(xmlTextReaderReadInnerXml(reader_), true);
}
std::wstring CefXmlReaderImpl::GetOuterXml()
{
if (!VerifyContext())
return std::wstring();
return xmlCharToWString(xmlTextReaderReadOuterXml(reader_), true);
}
int CefXmlReaderImpl::GetLineNumber()
{
if (!VerifyContext())
return -1;
return xmlTextReaderGetParserLineNumber(reader_);
}
bool CefXmlReaderImpl::MoveToAttribute(int index)
{
if (!VerifyContext())
return false;
return xmlTextReaderMoveToAttributeNo(reader_, index) == 1 ? true : false;
}
bool CefXmlReaderImpl::MoveToAttribute(const std::wstring& qualifiedName)
{
if (!VerifyContext())
return false;
std::string qualifiedNameStr = WideToUTF8(qualifiedName);
return xmlTextReaderMoveToAttribute(reader_,
BAD_CAST qualifiedNameStr.c_str()) == 1 ? true : false;
}
bool CefXmlReaderImpl::MoveToAttribute(const std::wstring& localName,
const std::wstring& namespaceURI)
{
if (!VerifyContext())
return false;
std::string localNameStr = WideToUTF8(localName);
std::string namespaceURIStr = WideToUTF8(namespaceURI);
return xmlTextReaderMoveToAttributeNs(reader_,
BAD_CAST localNameStr.c_str(), BAD_CAST namespaceURIStr.c_str()) == 1 ?
true : false;
}
bool CefXmlReaderImpl::MoveToFirstAttribute()
{
if (!VerifyContext())
return false;
return xmlTextReaderMoveToFirstAttribute(reader_) == 1 ? true : false;
}
bool CefXmlReaderImpl::MoveToNextAttribute()
{
if (!VerifyContext())
return false;
return xmlTextReaderMoveToNextAttribute(reader_) == 1 ? true : false;
}
bool CefXmlReaderImpl::MoveToCarryingElement()
{
if (!VerifyContext())
return false;
return xmlTextReaderMoveToElement(reader_) == 1 ? true : false;
}
void CefXmlReaderImpl::AppendError(const std::wstring& error_str)
{
if (!error_buf_.str().empty())
error_buf_ << L"\n";
error_buf_ << error_str;
}
bool CefXmlReaderImpl::VerifyContext()
{
if (PlatformThread::CurrentId() != supported_thread_id_) {
// This object should only be accessed from the thread that created it.
NOTREACHED();
return false;
}
return (reader_ != NULL);
}

69
libcef/xml_reader_impl.h Normal file
View File

@ -0,0 +1,69 @@
// Copyright (c) 20010 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#ifndef _XML_READER_IMPL_H
#define _XML_READER_IMPL_H
#include "../include/cef.h"
#include "base/platform_thread.h"
#include <libxml/xmlreader.h>
#include <sstream>
// Implementation of CefXmlReader
class CefXmlReaderImpl : public CefThreadSafeBase<CefXmlReader>
{
public:
CefXmlReaderImpl();
~CefXmlReaderImpl();
// Initialize the reader context.
bool Initialize(CefRefPtr<CefStreamReader> stream,
EncodingType encodingType, const std::wstring& URI);
virtual bool MoveToNextElement();
virtual bool Close();
virtual bool HasError();
virtual std::wstring GetError();
virtual NodeType GetType();
virtual int GetDepth();
virtual std::wstring GetLocalName();
virtual std::wstring GetPrefix();
virtual std::wstring GetQualifiedName();
virtual std::wstring GetNamespaceURI();
virtual std::wstring GetBaseURI();
virtual std::wstring GetXmlLang();
virtual bool IsEmptyElement();
virtual bool HasValue();
virtual std::wstring GetValue();
virtual bool HasAttributes();
virtual size_t GetAttributeCount();
virtual std::wstring GetAttribute(int index);
virtual std::wstring GetAttribute(const std::wstring& qualifiedName);
virtual std::wstring GetAttribute(const std::wstring& localName,
const std::wstring& namespaceURI);
virtual std::wstring GetInnerXml();
virtual std::wstring GetOuterXml();
virtual int GetLineNumber();
virtual bool MoveToAttribute(int index);
virtual bool MoveToAttribute(const std::wstring& qualifiedName);
virtual bool MoveToAttribute(const std::wstring& localName,
const std::wstring& namespaceURI);
virtual bool MoveToFirstAttribute();
virtual bool MoveToNextAttribute();
virtual bool MoveToCarryingElement();
// Add another line to the error string.
void AppendError(const std::wstring& error_str);
// Verify that the reader exists and is being accessed from the correct
// thread.
bool VerifyContext();
protected:
PlatformThreadId supported_thread_id_;
xmlTextReaderPtr reader_;
std::wstringstream error_buf_;
};
#endif // _XML_READER_IMPL_H

View File

@ -0,0 +1,409 @@
// Copyright (c) 2010 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// A portion of this file was generated by the CEF translator tool. When
// making changes by hand only do so within the body of existing function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
#include "libcef_dll/cpptoc/stream_reader_cpptoc.h"
#include "libcef_dll/cpptoc/xml_reader_cpptoc.h"
// GLOBAL FUNCTIONS - Body may be edited by hand.
CEF_EXPORT cef_xml_reader_t* cef_xml_reader_create(cef_stream_reader_t* stream,
enum cef_xml_encoding_type_t encodingType, const wchar_t* URI)
{
std::wstring encodingTypeStr;
if(encodingType)
encodingTypeStr = encodingType;
CefRefPtr<CefXmlReader> impl = CefXmlReader::Create(
CefStreamReaderCppToC::Unwrap(stream), encodingType, encodingTypeStr);
if(impl.get())
return CefXmlReaderCppToC::Wrap(impl);
return NULL;
}
// MEMBER FUNCTIONS - Body may be edited by hand.
int CEF_CALLBACK xml_reader_move_to_next_element(struct _cef_xml_reader_t* self)
{
DCHECK(self);
if(!self)
return 0;
return CefXmlReaderCppToC::Get(self)->MoveToNextElement();
}
int CEF_CALLBACK xml_reader_close(struct _cef_xml_reader_t* self)
{
DCHECK(self);
if(!self)
return 0;
return CefXmlReaderCppToC::Get(self)->Close();
}
int CEF_CALLBACK xml_reader_has_error(struct _cef_xml_reader_t* self)
{
DCHECK(self);
if(!self)
return 0;
return CefXmlReaderCppToC::Get(self)->HasError();
}
cef_string_t CEF_CALLBACK xml_reader_get_error(struct _cef_xml_reader_t* self)
{
DCHECK(self);
if(!self)
return NULL;
std::wstring retStr = CefXmlReaderCppToC::Get(self)->GetError();
if(!retStr.empty())
return cef_string_alloc(retStr.c_str());
return NULL;
}
enum cef_xml_node_type_t CEF_CALLBACK xml_reader_get_type(
struct _cef_xml_reader_t* self)
{
DCHECK(self);
if(!self)
return XML_NODE_UNSUPPORTED;
return CefXmlReaderCppToC::Get(self)->GetType();
}
int CEF_CALLBACK xml_reader_get_depth(struct _cef_xml_reader_t* self)
{
DCHECK(self);
if(!self)
return -1;
return CefXmlReaderCppToC::Get(self)->GetDepth();
}
cef_string_t CEF_CALLBACK xml_reader_get_local_name(
struct _cef_xml_reader_t* self)
{
DCHECK(self);
if(!self)
return NULL;
std::wstring retStr = CefXmlReaderCppToC::Get(self)->GetLocalName();
if(!retStr.empty())
return cef_string_alloc(retStr.c_str());
return NULL;
}
cef_string_t CEF_CALLBACK xml_reader_get_prefix(struct _cef_xml_reader_t* self)
{
DCHECK(self);
if(!self)
return NULL;
std::wstring retStr = CefXmlReaderCppToC::Get(self)->GetPrefix();
if(!retStr.empty())
return cef_string_alloc(retStr.c_str());
return NULL;
}
cef_string_t CEF_CALLBACK xml_reader_get_qualified_name(
struct _cef_xml_reader_t* self)
{
DCHECK(self);
if(!self)
return NULL;
std::wstring retStr = CefXmlReaderCppToC::Get(self)->GetQualifiedName();
if(!retStr.empty())
return cef_string_alloc(retStr.c_str());
return NULL;
}
cef_string_t CEF_CALLBACK xml_reader_get_namespace_uri(
struct _cef_xml_reader_t* self)
{
DCHECK(self);
if(!self)
return NULL;
std::wstring retStr = CefXmlReaderCppToC::Get(self)->GetNamespaceURI();
if(!retStr.empty())
return cef_string_alloc(retStr.c_str());
return NULL;
}
cef_string_t CEF_CALLBACK xml_reader_get_base_uri(
struct _cef_xml_reader_t* self)
{
DCHECK(self);
if(!self)
return NULL;
std::wstring retStr = CefXmlReaderCppToC::Get(self)->GetBaseURI();
if(!retStr.empty())
return cef_string_alloc(retStr.c_str());
return NULL;
}
cef_string_t CEF_CALLBACK xml_reader_get_xml_lang(
struct _cef_xml_reader_t* self)
{
DCHECK(self);
if(!self)
return NULL;
std::wstring retStr = CefXmlReaderCppToC::Get(self)->GetXmlLang();
if(!retStr.empty())
return cef_string_alloc(retStr.c_str());
return NULL;
}
int CEF_CALLBACK xml_reader_is_empty_element(struct _cef_xml_reader_t* self)
{
DCHECK(self);
if(!self)
return 0;
return CefXmlReaderCppToC::Get(self)->IsEmptyElement();
}
int CEF_CALLBACK xml_reader_has_value(struct _cef_xml_reader_t* self)
{
DCHECK(self);
if(!self)
return 0;
return CefXmlReaderCppToC::Get(self)->HasValue();
}
cef_string_t CEF_CALLBACK xml_reader_get_value(struct _cef_xml_reader_t* self)
{
DCHECK(self);
if(!self)
return NULL;
std::wstring retStr = CefXmlReaderCppToC::Get(self)->GetValue();
if(!retStr.empty())
return cef_string_alloc(retStr.c_str());
return NULL;
}
int CEF_CALLBACK xml_reader_has_attributes(struct _cef_xml_reader_t* self)
{
DCHECK(self);
if(!self)
return 0;
return CefXmlReaderCppToC::Get(self)->HasAttributes();
}
size_t CEF_CALLBACK xml_reader_get_attribute_count(
struct _cef_xml_reader_t* self)
{
DCHECK(self);
if(!self)
return 0;
return CefXmlReaderCppToC::Get(self)->GetAttributeCount();
}
cef_string_t CEF_CALLBACK xml_reader_get_attribute_byindex(
struct _cef_xml_reader_t* self, int index)
{
DCHECK(self);
if(!self)
return NULL;
std::wstring retStr = CefXmlReaderCppToC::Get(self)->GetAttribute(index);
if(!retStr.empty())
return cef_string_alloc(retStr.c_str());
return NULL;
}
cef_string_t CEF_CALLBACK xml_reader_get_attribute_byqname(
struct _cef_xml_reader_t* self, const wchar_t* qualifiedName)
{
DCHECK(self);
DCHECK(qualifiedName);
if(!self || !qualifiedName)
return NULL;
std::wstring retStr = CefXmlReaderCppToC::Get(self)->GetAttribute(
qualifiedName);
if(!retStr.empty())
return cef_string_alloc(retStr.c_str());
return NULL;
}
cef_string_t CEF_CALLBACK xml_reader_get_attribute_bylname(
struct _cef_xml_reader_t* self, const wchar_t* localName,
const wchar_t* namespaceURI)
{
DCHECK(self);
DCHECK(localName);
DCHECK(namespaceURI);
if(!self || !localName || !namespaceURI)
return NULL;
std::wstring retStr = CefXmlReaderCppToC::Get(self)->GetAttribute(
localName, namespaceURI);
if(!retStr.empty())
return cef_string_alloc(retStr.c_str());
return NULL;
}
cef_string_t CEF_CALLBACK xml_reader_get_inner_xml(
struct _cef_xml_reader_t* self)
{
DCHECK(self);
if(!self)
return NULL;
std::wstring retStr = CefXmlReaderCppToC::Get(self)->GetInnerXml();
if(!retStr.empty())
return cef_string_alloc(retStr.c_str());
return NULL;
}
cef_string_t CEF_CALLBACK xml_reader_get_outer_xml(
struct _cef_xml_reader_t* self)
{
DCHECK(self);
if(!self)
return NULL;
std::wstring retStr = CefXmlReaderCppToC::Get(self)->GetOuterXml();
if(!retStr.empty())
return cef_string_alloc(retStr.c_str());
return NULL;
}
int CEF_CALLBACK xml_reader_get_line_number(struct _cef_xml_reader_t* self)
{
DCHECK(self);
if(!self)
return 0;
return CefXmlReaderCppToC::Get(self)->GetLineNumber();
}
int CEF_CALLBACK xml_reader_move_to_attribute_byindex(
struct _cef_xml_reader_t* self, int index)
{
DCHECK(self);
if(!self)
return 0;
return CefXmlReaderCppToC::Get(self)->MoveToAttribute(index);
}
int CEF_CALLBACK xml_reader_move_to_attribute_byqname(
struct _cef_xml_reader_t* self, const wchar_t* qualifiedName)
{
DCHECK(self);
DCHECK(qualifiedName);
if(!self || !qualifiedName)
return 0;
return CefXmlReaderCppToC::Get(self)->MoveToAttribute(qualifiedName);
}
int CEF_CALLBACK xml_reader_move_to_attribute_bylname(
struct _cef_xml_reader_t* self, const wchar_t* localName,
const wchar_t* namespaceURI)
{
DCHECK(self);
DCHECK(localName);
DCHECK(namespaceURI);
if(!self || !localName || !namespaceURI)
return 0;
return CefXmlReaderCppToC::Get(self)->MoveToAttribute(localName,
namespaceURI);
}
int CEF_CALLBACK xml_reader_move_to_first_attribute(
struct _cef_xml_reader_t* self)
{
DCHECK(self);
if(!self)
return 0;
return CefXmlReaderCppToC::Get(self)->MoveToFirstAttribute();
}
int CEF_CALLBACK xml_reader_move_to_next_attribute(
struct _cef_xml_reader_t* self)
{
DCHECK(self);
if(!self)
return 0;
return CefXmlReaderCppToC::Get(self)->MoveToNextAttribute();
}
int CEF_CALLBACK xml_reader_move_to_carrying_element(
struct _cef_xml_reader_t* self)
{
DCHECK(self);
if(!self)
return 0;
return CefXmlReaderCppToC::Get(self)->MoveToCarryingElement();
}
// CONSTRUCTOR - Do not edit by hand.
CefXmlReaderCppToC::CefXmlReaderCppToC(CefXmlReader* cls)
: CefCppToC<CefXmlReaderCppToC, CefXmlReader, cef_xml_reader_t>(cls)
{
struct_.struct_.move_to_next_element = xml_reader_move_to_next_element;
struct_.struct_.close = xml_reader_close;
struct_.struct_.has_error = xml_reader_has_error;
struct_.struct_.get_error = xml_reader_get_error;
struct_.struct_.get_type = xml_reader_get_type;
struct_.struct_.get_depth = xml_reader_get_depth;
struct_.struct_.get_local_name = xml_reader_get_local_name;
struct_.struct_.get_prefix = xml_reader_get_prefix;
struct_.struct_.get_qualified_name = xml_reader_get_qualified_name;
struct_.struct_.get_namespace_uri = xml_reader_get_namespace_uri;
struct_.struct_.get_base_uri = xml_reader_get_base_uri;
struct_.struct_.get_xml_lang = xml_reader_get_xml_lang;
struct_.struct_.is_empty_element = xml_reader_is_empty_element;
struct_.struct_.has_value = xml_reader_has_value;
struct_.struct_.get_value = xml_reader_get_value;
struct_.struct_.has_attributes = xml_reader_has_attributes;
struct_.struct_.get_attribute_count = xml_reader_get_attribute_count;
struct_.struct_.get_attribute_byindex = xml_reader_get_attribute_byindex;
struct_.struct_.get_attribute_byqname = xml_reader_get_attribute_byqname;
struct_.struct_.get_attribute_bylname = xml_reader_get_attribute_bylname;
struct_.struct_.get_inner_xml = xml_reader_get_inner_xml;
struct_.struct_.get_outer_xml = xml_reader_get_outer_xml;
struct_.struct_.get_line_number = xml_reader_get_line_number;
struct_.struct_.move_to_attribute_byindex =
xml_reader_move_to_attribute_byindex;
struct_.struct_.move_to_attribute_byqname =
xml_reader_move_to_attribute_byqname;
struct_.struct_.move_to_attribute_bylname =
xml_reader_move_to_attribute_bylname;
struct_.struct_.move_to_first_attribute = xml_reader_move_to_first_attribute;
struct_.struct_.move_to_next_attribute = xml_reader_move_to_next_attribute;
struct_.struct_.move_to_carrying_element =
xml_reader_move_to_carrying_element;
}
#ifdef _DEBUG
long CefCppToC<CefXmlReaderCppToC, CefXmlReader, cef_xml_reader_t>::DebugObjCt =
0;
#endif

View File

@ -0,0 +1,34 @@
// Copyright (c) 2010 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool and should not edited
// by hand. See the translator.README.txt file in the tools directory for
// more information.
//
#ifndef _XMLREADER_CPPTOC_H
#define _XMLREADER_CPPTOC_H
#ifndef BUILDING_CEF_SHARED
#pragma message("Warning: "__FILE__" may be accessed DLL-side only")
#else // BUILDING_CEF_SHARED
#include "include/cef.h"
#include "include/cef_capi.h"
#include "libcef_dll/cpptoc/cpptoc.h"
// Wrap a C++ class with a C structure.
// This class may be instantiated and accessed DLL-side only.
class CefXmlReaderCppToC
: public CefCppToC<CefXmlReaderCppToC, CefXmlReader, cef_xml_reader_t>
{
public:
CefXmlReaderCppToC(CefXmlReader* cls);
virtual ~CefXmlReaderCppToC() {}
};
#endif // BUILDING_CEF_SHARED
#endif // _XMLREADER_CPPTOC_H

View File

@ -0,0 +1,366 @@
// Copyright (c) 2010 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// A portion of this file was generated by the CEF translator tool. When
// making changes by hand only do so within the body of existing static and
// virtual method implementations. See the translator.README.txt file in the
// tools directory for more information.
//
#include "libcef_dll/ctocpp/stream_reader_ctocpp.h"
#include "libcef_dll/ctocpp/xml_reader_ctocpp.h"
// STATIC METHODS - Body may be edited by hand.
CefRefPtr<CefXmlReader> CefXmlReader::Create(CefRefPtr<CefStreamReader> stream,
EncodingType encodingType, const std::wstring& URI)
{
cef_xml_reader_t* impl = cef_xml_reader_create(
CefStreamReaderCToCpp::Unwrap(stream), encodingType, URI.c_str());
if(impl)
return CefXmlReaderCToCpp::Wrap(impl);
return NULL;
}
// VIRTUAL METHODS - Body may be edited by hand.
bool CefXmlReaderCToCpp::MoveToNextElement()
{
if(CEF_MEMBER_MISSING(struct_, move_to_next_element))
return false;
return struct_->move_to_next_element(struct_) ? true : false;
}
bool CefXmlReaderCToCpp::Close()
{
if(CEF_MEMBER_MISSING(struct_, close))
return false;
return struct_->close(struct_) ? true : false;
}
bool CefXmlReaderCToCpp::HasError()
{
if(CEF_MEMBER_MISSING(struct_, has_error))
return false;
return struct_->has_error(struct_) ? true : false;
}
std::wstring CefXmlReaderCToCpp::GetError()
{
std::wstring str;
if(CEF_MEMBER_MISSING(struct_, get_error))
return str;
cef_string_t cef_str = struct_->get_error(struct_);
if(cef_str) {
str = cef_str;
cef_string_free(cef_str);
}
return str;
}
CefXmlReader::NodeType CefXmlReaderCToCpp::GetType()
{
if(CEF_MEMBER_MISSING(struct_, get_type))
return XML_NODE_UNSUPPORTED;
return struct_->get_type(struct_);
}
int CefXmlReaderCToCpp::GetDepth()
{
if(CEF_MEMBER_MISSING(struct_, get_depth))
return -1;
return struct_->get_depth(struct_);
}
std::wstring CefXmlReaderCToCpp::GetLocalName()
{
std::wstring str;
if(CEF_MEMBER_MISSING(struct_, get_local_name))
return str;
cef_string_t cef_str = struct_->get_local_name(struct_);
if(cef_str) {
str = cef_str;
cef_string_free(cef_str);
}
return str;
}
std::wstring CefXmlReaderCToCpp::GetPrefix()
{
std::wstring str;
if(CEF_MEMBER_MISSING(struct_, get_prefix))
return str;
cef_string_t cef_str = struct_->get_prefix(struct_);
if(cef_str) {
str = cef_str;
cef_string_free(cef_str);
}
return str;
}
std::wstring CefXmlReaderCToCpp::GetQualifiedName()
{
std::wstring str;
if(CEF_MEMBER_MISSING(struct_, get_qualified_name))
return str;
cef_string_t cef_str = struct_->get_qualified_name(struct_);
if(cef_str) {
str = cef_str;
cef_string_free(cef_str);
}
return str;
}
std::wstring CefXmlReaderCToCpp::GetNamespaceURI()
{
std::wstring str;
if(CEF_MEMBER_MISSING(struct_, get_namespace_uri))
return str;
cef_string_t cef_str = struct_->get_namespace_uri(struct_);
if(cef_str) {
str = cef_str;
cef_string_free(cef_str);
}
return str;
}
std::wstring CefXmlReaderCToCpp::GetBaseURI()
{
std::wstring str;
if(CEF_MEMBER_MISSING(struct_, get_base_uri))
return str;
cef_string_t cef_str = struct_->get_base_uri(struct_);
if(cef_str) {
str = cef_str;
cef_string_free(cef_str);
}
return str;
}
std::wstring CefXmlReaderCToCpp::GetXmlLang()
{
std::wstring str;
if(CEF_MEMBER_MISSING(struct_, get_xml_lang))
return str;
cef_string_t cef_str = struct_->get_xml_lang(struct_);
if(cef_str) {
str = cef_str;
cef_string_free(cef_str);
}
return str;
}
bool CefXmlReaderCToCpp::IsEmptyElement()
{
if(CEF_MEMBER_MISSING(struct_, is_empty_element))
return false;
return struct_->is_empty_element(struct_) ? true : false;
}
bool CefXmlReaderCToCpp::HasValue()
{
if(CEF_MEMBER_MISSING(struct_, has_value))
return false;
return struct_->has_value(struct_) ? true : false;
}
std::wstring CefXmlReaderCToCpp::GetValue()
{
std::wstring str;
if(CEF_MEMBER_MISSING(struct_, get_value))
return str;
cef_string_t cef_str = struct_->get_value(struct_);
if(cef_str) {
str = cef_str;
cef_string_free(cef_str);
}
return str;
}
bool CefXmlReaderCToCpp::HasAttributes()
{
if(CEF_MEMBER_MISSING(struct_, has_attributes))
return false;
return struct_->has_attributes(struct_) ? true : false;
}
size_t CefXmlReaderCToCpp::GetAttributeCount()
{
if(CEF_MEMBER_MISSING(struct_, get_attribute_count))
return 0;
return struct_->get_attribute_count(struct_);
}
std::wstring CefXmlReaderCToCpp::GetAttribute(int index)
{
std::wstring str;
if(CEF_MEMBER_MISSING(struct_, get_attribute_byindex))
return str;
cef_string_t cef_str = struct_->get_attribute_byindex(struct_, index);
if(cef_str) {
str = cef_str;
cef_string_free(cef_str);
}
return str;
}
std::wstring CefXmlReaderCToCpp::GetAttribute(const std::wstring& qualifiedName)
{
std::wstring str;
if(CEF_MEMBER_MISSING(struct_, get_attribute_byqname))
return str;
cef_string_t cef_str = struct_->get_attribute_byqname(struct_,
qualifiedName.c_str());
if(cef_str) {
str = cef_str;
cef_string_free(cef_str);
}
return str;
}
std::wstring CefXmlReaderCToCpp::GetAttribute(const std::wstring& localName,
const std::wstring& namespaceURI)
{
std::wstring str;
if(CEF_MEMBER_MISSING(struct_, get_attribute_bylname))
return str;
cef_string_t cef_str = struct_->get_attribute_bylname(struct_,
localName.c_str(), namespaceURI.c_str());
if(cef_str) {
str = cef_str;
cef_string_free(cef_str);
}
return str;
}
std::wstring CefXmlReaderCToCpp::GetInnerXml()
{
std::wstring str;
if(CEF_MEMBER_MISSING(struct_, get_inner_xml))
return str;
cef_string_t cef_str = struct_->get_inner_xml(struct_);
if(cef_str) {
str = cef_str;
cef_string_free(cef_str);
}
return str;
}
std::wstring CefXmlReaderCToCpp::GetOuterXml()
{
std::wstring str;
if(CEF_MEMBER_MISSING(struct_, get_outer_xml))
return str;
cef_string_t cef_str = struct_->get_outer_xml(struct_);
if(cef_str) {
str = cef_str;
cef_string_free(cef_str);
}
return str;
}
int CefXmlReaderCToCpp::GetLineNumber()
{
if(CEF_MEMBER_MISSING(struct_, get_line_number))
return false;
return struct_->get_line_number(struct_);
}
bool CefXmlReaderCToCpp::MoveToAttribute(int index)
{
if(CEF_MEMBER_MISSING(struct_, move_to_attribute_byindex))
return false;
return struct_->move_to_attribute_byindex(struct_, index) ? true : false;
}
bool CefXmlReaderCToCpp::MoveToAttribute(const std::wstring& qualifiedName)
{
if(CEF_MEMBER_MISSING(struct_, move_to_attribute_byqname))
return false;
return struct_->move_to_attribute_byqname(struct_, qualifiedName.c_str()) ?
true : false;
}
bool CefXmlReaderCToCpp::MoveToAttribute(const std::wstring& localName,
const std::wstring& namespaceURI)
{
if(CEF_MEMBER_MISSING(struct_, move_to_attribute_bylname))
return false;
return struct_->move_to_attribute_bylname(struct_, localName.c_str(),
namespaceURI.c_str()) ? true : false;
}
bool CefXmlReaderCToCpp::MoveToFirstAttribute()
{
if(CEF_MEMBER_MISSING(struct_, move_to_first_attribute))
return false;
return struct_->move_to_first_attribute(struct_) ? true : false;
}
bool CefXmlReaderCToCpp::MoveToNextAttribute()
{
if(CEF_MEMBER_MISSING(struct_, move_to_next_attribute))
return false;
return struct_->move_to_next_attribute(struct_) ? true : false;
}
bool CefXmlReaderCToCpp::MoveToCarryingElement()
{
if(CEF_MEMBER_MISSING(struct_, move_to_carrying_element))
return false;
return struct_->move_to_carrying_element(struct_) ? true : false;
}
#ifdef _DEBUG
long CefCToCpp<CefXmlReaderCToCpp, CefXmlReader, cef_xml_reader_t>::DebugObjCt =
0;
#endif

View File

@ -0,0 +1,69 @@
// Copyright (c) 2010 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// -------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool and should not edited
// by hand. See the translator.README.txt file in the tools directory for
// more information.
//
#ifndef _XMLREADER_CTOCPP_H
#define _XMLREADER_CTOCPP_H
#ifndef USING_CEF_SHARED
#pragma message("Warning: "__FILE__" may be accessed wrapper-side only")
#else // USING_CEF_SHARED
#include "include/cef.h"
#include "include/cef_capi.h"
#include "libcef_dll/ctocpp/ctocpp.h"
// Wrap a C structure with a C++ class.
// This class may be instantiated and accessed wrapper-side only.
class CefXmlReaderCToCpp
: public CefCToCpp<CefXmlReaderCToCpp, CefXmlReader, cef_xml_reader_t>
{
public:
CefXmlReaderCToCpp(cef_xml_reader_t* str)
: CefCToCpp<CefXmlReaderCToCpp, CefXmlReader, cef_xml_reader_t>(str) {}
virtual ~CefXmlReaderCToCpp() {}
// CefXmlReader methods
virtual bool MoveToNextElement();
virtual bool Close();
virtual bool HasError();
virtual std::wstring GetError();
virtual NodeType GetType();
virtual int GetDepth();
virtual std::wstring GetLocalName();
virtual std::wstring GetPrefix();
virtual std::wstring GetQualifiedName();
virtual std::wstring GetNamespaceURI();
virtual std::wstring GetBaseURI();
virtual std::wstring GetXmlLang();
virtual bool IsEmptyElement();
virtual bool HasValue();
virtual std::wstring GetValue();
virtual bool HasAttributes();
virtual size_t GetAttributeCount();
virtual std::wstring GetAttribute(int index);
virtual std::wstring GetAttribute(const std::wstring& qualifiedName);
virtual std::wstring GetAttribute(const std::wstring& localName,
const std::wstring& namespaceURI);
virtual std::wstring GetInnerXml();
virtual std::wstring GetOuterXml();
virtual int GetLineNumber();
virtual bool MoveToAttribute(int index);
virtual bool MoveToAttribute(const std::wstring& qualifiedName);
virtual bool MoveToAttribute(const std::wstring& localName,
const std::wstring& namespaceURI);
virtual bool MoveToFirstAttribute();
virtual bool MoveToNextAttribute();
virtual bool MoveToCarryingElement();
};
#endif // USING_CEF_SHARED
#endif // _XMLREADER_CTOCPP_H

View File

@ -14,6 +14,7 @@
#include "cpptoc/stream_reader_cpptoc.h" #include "cpptoc/stream_reader_cpptoc.h"
#include "cpptoc/stream_writer_cpptoc.h" #include "cpptoc/stream_writer_cpptoc.h"
#include "cpptoc/v8value_cpptoc.h" #include "cpptoc/v8value_cpptoc.h"
#include "cpptoc/xml_reader_cpptoc.h"
#include "ctocpp/download_handler_ctocpp.h" #include "ctocpp/download_handler_ctocpp.h"
#include "ctocpp/handler_ctocpp.h" #include "ctocpp/handler_ctocpp.h"
#include "ctocpp/read_handler_ctocpp.h" #include "ctocpp/read_handler_ctocpp.h"
@ -47,6 +48,7 @@ CEF_EXPORT void cef_shutdown()
DCHECK(CefStreamReaderCppToC::DebugObjCt == 0); DCHECK(CefStreamReaderCppToC::DebugObjCt == 0);
DCHECK(CefStreamWriterCppToC::DebugObjCt == 0); DCHECK(CefStreamWriterCppToC::DebugObjCt == 0);
DCHECK(CefV8ValueCppToC::DebugObjCt == 0); DCHECK(CefV8ValueCppToC::DebugObjCt == 0);
DCHECK(CefXmlReaderCppToC::DebugObjCt == 0);
DCHECK(CefDownloadHandlerCToCpp::DebugObjCt == 0); DCHECK(CefDownloadHandlerCToCpp::DebugObjCt == 0);
DCHECK(CefHandlerCToCpp::DebugObjCt == 0); DCHECK(CefHandlerCToCpp::DebugObjCt == 0);
DCHECK(CefReadHandlerCToCpp::DebugObjCt == 0); DCHECK(CefReadHandlerCToCpp::DebugObjCt == 0);

View File

@ -0,0 +1,488 @@
// Copyright (c) 2010 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#include "include/cef_wrapper.h"
#include "base/logging.h"
namespace {
class CefXmlObjectLoader
{
public:
CefXmlObjectLoader(CefRefPtr<CefXmlObject> root_object)
: root_object_(root_object)
{
}
bool Load(CefRefPtr<CefStreamReader> stream,
CefXmlReader::EncodingType encodingType,
const std::wstring& URI)
{
CefRefPtr<CefXmlReader> reader(
CefXmlReader::Create(stream, encodingType, URI));
if (!reader.get())
return false;
bool ret = reader->MoveToNextElement();
if (ret) {
CefRefPtr<CefXmlObject> cur_object(root_object_), new_object;
CefXmlObject::ObjectVector queue;
int cur_depth, value_depth = -1;
CefXmlReader::NodeType cur_type;
std::wstringstream cur_value;
bool last_has_ns = false;
queue.push_back(root_object_);
do {
cur_depth = reader->GetDepth();
if (value_depth >= 0 && cur_depth > value_depth) {
// The current node has already been parsed as part of a value.
continue;
}
cur_type = reader->GetType();
if (cur_type == XML_NODE_ELEMENT_START) {
if (cur_depth == value_depth) {
// Add to the current value.
cur_value << reader->GetOuterXml();
continue;
} else if(last_has_ns && reader->GetPrefix().empty()) {
if (!cur_object->HasChildren()) {
// Start a new value because the last element has a namespace and
// this element does not.
value_depth = cur_depth;
cur_value << reader->GetOuterXml();
} else {
// Value following a child element is not allowed.
std::wstringstream ss;
ss << L"Value following child element, line " <<
reader->GetLineNumber();
load_error_ = ss.str();
ret = false;
break;
}
} else {
// Start a new element.
new_object = new CefXmlObject(reader->GetQualifiedName());
cur_object->AddChild(new_object);
last_has_ns = !reader->GetPrefix().empty();
if (!reader->IsEmptyElement()) {
// The new element potentially has a value and/or children, so
// set the current object and add the object to the queue.
cur_object = new_object;
queue.push_back(cur_object);
}
if (reader->HasAttributes() && reader->MoveToFirstAttribute()) {
// Read all object attributes.
do {
new_object->SetAttributeValue(reader->GetQualifiedName(),
reader->GetValue());
} while(reader->MoveToNextAttribute());
reader->MoveToCarryingElement();
}
}
} else if(cur_type == XML_NODE_ELEMENT_END) {
if (cur_depth == value_depth) {
// Ending an element that is already in the value.
continue;
} else if (cur_depth < value_depth) {
// Done with parsing the value portion of the current element.
cur_object->SetValue(cur_value.str());
cur_value.str(L"");
value_depth = -1;
}
// Pop the current element from the queue.
queue.pop_back();
if (queue.empty() ||
cur_object->GetName() != reader->GetQualifiedName()) {
// Open tag without close tag or close tag without open tag should
// never occur (the parser catches this error).
NOTREACHED();
std::wstringstream ss;
ss << L"Mismatched end tag for " << cur_object->GetName() <<
L", line " << reader->GetLineNumber();
load_error_ = ss.str();
ret = false;
break;
}
// Set the current object to the previous object in the queue.
cur_object = queue.back().get();
} else if(cur_type == XML_NODE_TEXT || cur_type == XML_NODE_CDATA ||
cur_type == XML_NODE_ENTITY_REFERENCE) {
if (cur_depth == value_depth) {
// Add to the current value.
cur_value << reader->GetValue();
} else if (!cur_object->HasChildren()) {
// Start a new value.
value_depth = cur_depth;
cur_value << reader->GetValue();
} else {
// Value following a child element is not allowed.
std::wstringstream ss;
ss << L"Value following child element, line " <<
reader->GetLineNumber();
load_error_ = ss.str();
ret = false;
break;
}
}
} while(reader->MoveToNextElement());
}
if (reader->HasError()) {
load_error_ = reader->GetError();
return false;
}
return ret;
}
std::wstring GetLoadError() { return load_error_; }
private:
std::wstring load_error_;
CefRefPtr<CefXmlObject> root_object_;
};
} // namespace
CefXmlObject::CefXmlObject(const std::wstring& name)
: name_(name), parent_(NULL)
{
}
CefXmlObject::~CefXmlObject()
{
}
bool CefXmlObject::Load(CefRefPtr<CefStreamReader> stream,
CefXmlReader::EncodingType encodingType,
const std::wstring& URI, std::wstring* loadError)
{
AutoLock lock_scope(this);
Clear();
CefXmlObjectLoader loader(this);
if (!loader.Load(stream, encodingType, URI)) {
if (loadError)
*loadError = loader.GetLoadError();
return false;
}
return true;
}
void CefXmlObject::Set(CefRefPtr<CefXmlObject> object)
{
DCHECK(object.get());
AutoLock lock_scope1(this);
AutoLock lock_scope2(object);
Clear();
name_ = object->GetName();
Append(object, true);
}
void CefXmlObject::Append(CefRefPtr<CefXmlObject> object,
bool overwriteAttributes)
{
DCHECK(object.get());
AutoLock lock_scope1(this);
AutoLock lock_scope2(object);
if (object->HasChildren()) {
ObjectVector children;
object->GetChildren(children);
ObjectVector::const_iterator it = children.begin();
for (; it != children.end(); ++it)
AddChild((*it)->Duplicate());
}
if (object->HasAttributes()) {
AttributeMap attributes;
object->GetAttributes(attributes);
AttributeMap::const_iterator it = attributes.begin();
for (; it != attributes.end(); ++it) {
if (overwriteAttributes || !HasAttribute(it->first))
SetAttributeValue(it->first, it->second);
}
}
}
CefRefPtr<CefXmlObject> CefXmlObject::Duplicate()
{
CefRefPtr<CefXmlObject> new_obj;
{
AutoLock lock_scope(this);
new_obj = new CefXmlObject(name_);
new_obj->Append(this, true);
}
return new_obj;
}
void CefXmlObject::Clear()
{
AutoLock lock_scope(this);
ClearChildren();
ClearAttributes();
}
std::wstring CefXmlObject::GetName()
{
std::wstring name;
{
AutoLock lock_scope(this);
name = name_;
}
return name;
}
bool CefXmlObject::SetName(const std::wstring& name)
{
DCHECK(!name.empty());
if (name.empty())
return false;
AutoLock lock_scope(this);
name_ = name;
return true;
}
bool CefXmlObject::HasParent()
{
AutoLock lock_scope(this);
return (parent_ != NULL);
}
CefRefPtr<CefXmlObject> CefXmlObject::GetParent()
{
CefRefPtr<CefXmlObject> parent;
{
AutoLock lock_scope(this);
parent = parent_;
}
return parent;
}
bool CefXmlObject::HasValue()
{
AutoLock lock_scope(this);
return !value_.empty();
}
std::wstring CefXmlObject::GetValue()
{
std::wstring value;
{
AutoLock lock_scope(this);
value = value_;
}
return value;
}
bool CefXmlObject::SetValue(const std::wstring& value)
{
AutoLock lock_scope(this);
DCHECK(children_.empty());
if (!children_.empty())
return false;
value_ = value;
return true;
}
bool CefXmlObject::HasAttributes()
{
AutoLock lock_scope(this);
return !attributes_.empty();
}
size_t CefXmlObject::GetAttributeCount()
{
AutoLock lock_scope(this);
return attributes_.size();
}
bool CefXmlObject::HasAttribute(const std::wstring& name)
{
if (name.empty())
return false;
AutoLock lock_scope(this);
AttributeMap::const_iterator it = attributes_.find(name);
return (it != attributes_.end());
}
std::wstring CefXmlObject::GetAttributeValue(const std::wstring& name)
{
DCHECK(!name.empty());
std::wstring value;
if (!name.empty()) {
AutoLock lock_scope(this);
AttributeMap::const_iterator it = attributes_.find(name);
if (it != attributes_.end())
value = it->second;
}
return value;
}
bool CefXmlObject::SetAttributeValue(const std::wstring& name,
const std::wstring& value)
{
DCHECK(!name.empty());
if (name.empty())
return false;
AutoLock lock_scope(this);
AttributeMap::iterator it = attributes_.find(name);
if (it != attributes_.end()) {
it->second = value;
} else {
attributes_.insert(
std::make_pair<std::wstring,std::wstring>(name, value));
}
return true;
}
size_t CefXmlObject::GetAttributes(AttributeMap& attributes)
{
AutoLock lock_scope(this);
attributes = attributes_;
return attributes_.size();
}
void CefXmlObject::ClearAttributes()
{
AutoLock lock_scope(this);
attributes_.clear();
}
bool CefXmlObject::HasChildren()
{
AutoLock lock_scope(this);
return !children_.empty();
}
size_t CefXmlObject::GetChildCount()
{
AutoLock lock_scope(this);
return children_.size();
}
bool CefXmlObject::HasChild(CefRefPtr<CefXmlObject> child)
{
DCHECK(child.get());
AutoLock lock_scope(this);
ObjectVector::const_iterator it = children_.begin();
for (; it != children_.end(); ++it) {
if ((*it).get() == child.get())
return true;
}
return false;
}
bool CefXmlObject::AddChild(CefRefPtr<CefXmlObject> child)
{
DCHECK(child.get());
if (!child.get())
return false;
AutoLock lock_scope1(child);
DCHECK(child->GetParent() == NULL);
if (child->GetParent() != NULL)
return false;
AutoLock lock_scope2(this);
children_.push_back(child);
child->SetParent(this);
return true;
}
bool CefXmlObject::RemoveChild(CefRefPtr<CefXmlObject> child)
{
DCHECK(child.get());
AutoLock lock_scope(this);
ObjectVector::iterator it = children_.begin();
for (; it != children_.end(); ++it) {
if ((*it).get() == child.get()) {
children_.erase(it);
child->SetParent(NULL);
return true;
}
}
return false;
}
size_t CefXmlObject::GetChildren(ObjectVector& children)
{
AutoLock lock_scope(this);
children = children_;
return children_.size();
}
void CefXmlObject::ClearChildren()
{
AutoLock lock_scope(this);
ObjectVector::iterator it = children_.begin();
for (; it != children_.end(); ++it)
(*it)->SetParent(NULL);
children_.clear();
}
CefRefPtr<CefXmlObject> CefXmlObject::FindChild(const std::wstring& name)
{
DCHECK(!name.empty());
if (name.empty())
return NULL;
AutoLock lock_scope(this);
ObjectVector::const_iterator it = children_.begin();
for (; it != children_.end(); ++it) {
if((*it)->GetName() == name)
return (*it);
}
return NULL;
}
size_t CefXmlObject::FindChildren(const std::wstring& name,
ObjectVector& children)
{
DCHECK(!name.empty());
if (name.empty())
return 0;
size_t ct = 0;
AutoLock lock_scope(this);
ObjectVector::const_iterator it = children_.begin();
for (; it != children_.end(); ++it) {
if((*it)->GetName() == name) {
children.push_back(*it);
ct++;
}
}
return ct;
}
void CefXmlObject::SetParent(CefXmlObject* parent)
{
AutoLock lock_scope(this);
if (parent) {
DCHECK(parent_ == NULL);
parent_ = parent;
} else {
DCHECK(parent_ != NULL);
parent_ = NULL;
}
}

View File

@ -1,4 +1,4 @@
// Copyright (c) 2009 The Chromium Embedded Framework Authors. All rights // Copyright (c) 2010 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that // reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file. // can be found in the LICENSE file.
@ -21,6 +21,7 @@
#include "libcef_dll/ctocpp/stream_reader_ctocpp.h" #include "libcef_dll/ctocpp/stream_reader_ctocpp.h"
#include "libcef_dll/ctocpp/stream_writer_ctocpp.h" #include "libcef_dll/ctocpp/stream_writer_ctocpp.h"
#include "libcef_dll/ctocpp/v8value_ctocpp.h" #include "libcef_dll/ctocpp/v8value_ctocpp.h"
#include "libcef_dll/ctocpp/xml_reader_ctocpp.h"
bool CefInitialize(bool multi_threaded_message_loop, bool CefInitialize(bool multi_threaded_message_loop,
@ -50,6 +51,7 @@ void CefShutdown()
DCHECK(CefStreamReaderCToCpp::DebugObjCt == 0); DCHECK(CefStreamReaderCToCpp::DebugObjCt == 0);
DCHECK(CefStreamWriterCToCpp::DebugObjCt == 0); DCHECK(CefStreamWriterCToCpp::DebugObjCt == 0);
DCHECK(CefV8ValueCToCpp::DebugObjCt == 0); DCHECK(CefV8ValueCToCpp::DebugObjCt == 0);
DCHECK(CefXmlReaderCToCpp::DebugObjCt == 0);
#endif // _DEBUG #endif // _DEBUG
} }

View File

@ -0,0 +1,644 @@
// Copyright (c) 2010 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#include "include/cef.h"
#include "include/cef_wrapper.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
char g_test_xml[] =
"<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n"
"<?my_instruction my_value?>\n"
"<!DOCTYPE my_document SYSTEM \"example.dtd\" [\n"
" <!ENTITY EA \"EA Value\">\n"
" <!ENTITY EB \"EB Value\">\n"
"]>\n"
"<ns:obj xmlns:ns=\"http://www.example.org/ns\">\n"
" <ns:objA>value A</ns:objA>\n"
" <!-- my comment -->\n"
" <ns:objB>\n"
" <ns:objB_1>value B1</ns:objB_1>\n"
" <ns:objB_2><![CDATA[some <br/> data]]></ns:objB_2>\n"
" <ns:objB_3>&EB;</ns:objB_3>\n"
" <ns:objB_4><b>this is</b> mixed content &EA;</ns:objB_4>\n"
" </ns:objB>\n"
" <ns:objC ns:attr1=\"value C1\" ns:attr2=\"value C2\"/><ns:objD></ns:objD>\n"
"</ns:obj>\n";
} // namespace
// Test XML reading
TEST(XmlReaderTest, Read)
{
// Create the stream reader.
CefRefPtr<CefStreamReader> stream(
CefStreamReader::CreateForData(g_test_xml, sizeof(g_test_xml) - 1));
ASSERT_TRUE(stream.get() != NULL);
// Create the XML reader.
CefRefPtr<CefXmlReader> reader(
CefXmlReader::Create(stream, XML_ENCODING_NONE,
L"http://www.example.org/example.xml"));
ASSERT_TRUE(reader.get() != NULL);
// Move to the processing instruction node.
ASSERT_TRUE(reader->MoveToNextElement());
ASSERT_EQ(reader->GetDepth(), 0);
ASSERT_EQ(reader->GetType(), XML_NODE_PROCESSING_INSTRUCTION);
ASSERT_EQ(reader->GetLocalName(), L"my_instruction");
ASSERT_EQ(reader->GetQualifiedName(), L"my_instruction");
ASSERT_TRUE(reader->HasValue());
ASSERT_EQ(reader->GetValue(), L"my_value");
// Move to the DOCTYPE node.
ASSERT_TRUE(reader->MoveToNextElement());
ASSERT_EQ(reader->GetDepth(), 0);
ASSERT_EQ(reader->GetType(), XML_NODE_DOCUMENT_TYPE);
ASSERT_EQ(reader->GetLocalName(), L"my_document");
ASSERT_EQ(reader->GetQualifiedName(), L"my_document");
ASSERT_FALSE(reader->HasValue());
// Move to ns:obj element start node.
ASSERT_TRUE(reader->MoveToNextElement());
ASSERT_EQ(reader->GetDepth(), 0);
ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_START);
ASSERT_EQ(reader->GetLocalName(), L"obj");
ASSERT_EQ(reader->GetPrefix(), L"ns");
ASSERT_EQ(reader->GetQualifiedName(), L"ns:obj");
ASSERT_EQ(reader->GetNamespaceURI(), L"http://www.example.org/ns");
ASSERT_TRUE(reader->HasAttributes());
ASSERT_EQ(reader->GetAttributeCount(), 1);
ASSERT_EQ(reader->GetAttribute(0), L"http://www.example.org/ns");
ASSERT_EQ(reader->GetAttribute(L"xmlns:ns"), L"http://www.example.org/ns");
ASSERT_EQ(reader->GetAttribute(L"ns", L"http://www.w3.org/2000/xmlns/"),
L"http://www.example.org/ns");
// Move to the whitespace node.
ASSERT_TRUE(reader->MoveToNextElement());
ASSERT_EQ(reader->GetType(), XML_NODE_WHITESPACE);
// Move to the ns:objA element start node.
ASSERT_TRUE(reader->MoveToNextElement());
ASSERT_EQ(reader->GetDepth(), 1);
ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_START);
ASSERT_EQ(reader->GetLocalName(), L"objA");
ASSERT_EQ(reader->GetPrefix(), L"ns");
ASSERT_EQ(reader->GetQualifiedName(), L"ns:objA");
ASSERT_EQ(reader->GetNamespaceURI(), L"http://www.example.org/ns");
ASSERT_FALSE(reader->IsEmptyElement());
ASSERT_FALSE(reader->HasAttributes());
ASSERT_FALSE(reader->HasValue());
// Move to the ns:objA value node.
ASSERT_TRUE(reader->MoveToNextElement());
ASSERT_EQ(reader->GetDepth(), 2);
ASSERT_EQ(reader->GetType(), XML_NODE_TEXT);
ASSERT_EQ(reader->GetLocalName(), L"#text");
ASSERT_EQ(reader->GetQualifiedName(), L"#text");
ASSERT_TRUE(reader->HasValue());
ASSERT_EQ(reader->GetValue(), L"value A");
// Move to the ns:objA element ending node.
ASSERT_TRUE(reader->MoveToNextElement());
ASSERT_EQ(reader->GetDepth(), 1);
ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_END);
ASSERT_EQ(reader->GetLocalName(), L"objA");
ASSERT_EQ(reader->GetPrefix(), L"ns");
ASSERT_EQ(reader->GetQualifiedName(), L"ns:objA");
ASSERT_EQ(reader->GetNamespaceURI(), L"http://www.example.org/ns");
ASSERT_FALSE(reader->IsEmptyElement());
ASSERT_FALSE(reader->HasAttributes());
ASSERT_FALSE(reader->HasValue());
// Move to the whitespace node.
ASSERT_TRUE(reader->MoveToNextElement());
ASSERT_EQ(reader->GetDepth(), 1);
ASSERT_EQ(reader->GetType(), XML_NODE_WHITESPACE);
// Move to the comment node.
ASSERT_TRUE(reader->MoveToNextElement());
ASSERT_EQ(reader->GetDepth(), 1);
ASSERT_EQ(reader->GetType(), XML_NODE_COMMENT);
ASSERT_EQ(reader->GetLocalName(), L"#comment");
ASSERT_EQ(reader->GetQualifiedName(), L"#comment");
ASSERT_TRUE(reader->HasValue());
ASSERT_EQ(reader->GetValue(), L" my comment ");
// Move to the whitespace node.
ASSERT_TRUE(reader->MoveToNextElement());
ASSERT_EQ(reader->GetType(), XML_NODE_WHITESPACE);
// Move to the ns:objB element start node.
ASSERT_TRUE(reader->MoveToNextElement());
ASSERT_EQ(reader->GetDepth(), 1);
ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_START);
ASSERT_EQ(reader->GetLocalName(), L"objB");
ASSERT_EQ(reader->GetPrefix(), L"ns");
ASSERT_EQ(reader->GetQualifiedName(), L"ns:objB");
ASSERT_EQ(reader->GetNamespaceURI(), L"http://www.example.org/ns");
ASSERT_FALSE(reader->IsEmptyElement());
ASSERT_FALSE(reader->HasAttributes());
ASSERT_FALSE(reader->HasValue());
// Move to the whitespace node.
ASSERT_TRUE(reader->MoveToNextElement());
ASSERT_EQ(reader->GetType(), XML_NODE_WHITESPACE);
// Move to the ns:objB_1 element start node.
ASSERT_TRUE(reader->MoveToNextElement());
ASSERT_EQ(reader->GetDepth(), 2);
ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_START);
ASSERT_EQ(reader->GetLocalName(), L"objB_1");
ASSERT_EQ(reader->GetPrefix(), L"ns");
ASSERT_EQ(reader->GetQualifiedName(), L"ns:objB_1");
ASSERT_EQ(reader->GetNamespaceURI(), L"http://www.example.org/ns");
ASSERT_FALSE(reader->IsEmptyElement());
ASSERT_FALSE(reader->HasAttributes());
ASSERT_FALSE(reader->HasValue());
// Move to the ns:objB_1 value node.
ASSERT_TRUE(reader->MoveToNextElement());
ASSERT_EQ(reader->GetDepth(), 3);
ASSERT_EQ(reader->GetType(), XML_NODE_TEXT);
ASSERT_TRUE(reader->HasValue());
ASSERT_EQ(reader->GetValue(), L"value B1");
// Move to the ns:objB_1 element ending node.
ASSERT_TRUE(reader->MoveToNextElement());
ASSERT_EQ(reader->GetDepth(), 2);
ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_END);
ASSERT_EQ(reader->GetLocalName(), L"objB_1");
ASSERT_EQ(reader->GetPrefix(), L"ns");
ASSERT_EQ(reader->GetQualifiedName(), L"ns:objB_1");
ASSERT_EQ(reader->GetNamespaceURI(), L"http://www.example.org/ns");
ASSERT_FALSE(reader->IsEmptyElement());
ASSERT_FALSE(reader->HasAttributes());
ASSERT_FALSE(reader->HasValue());
// Move to the whitespace node.
ASSERT_TRUE(reader->MoveToNextElement());
ASSERT_EQ(reader->GetType(), XML_NODE_WHITESPACE);
// Move to the ns:objB_2 element start node.
ASSERT_TRUE(reader->MoveToNextElement());
ASSERT_EQ(reader->GetDepth(), 2);
ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_START);
ASSERT_EQ(reader->GetLocalName(), L"objB_2");
ASSERT_EQ(reader->GetPrefix(), L"ns");
ASSERT_EQ(reader->GetQualifiedName(), L"ns:objB_2");
ASSERT_EQ(reader->GetNamespaceURI(), L"http://www.example.org/ns");
ASSERT_FALSE(reader->IsEmptyElement());
ASSERT_FALSE(reader->HasAttributes());
ASSERT_FALSE(reader->HasValue());
// Move to the ns:objB_2 value node.
ASSERT_TRUE(reader->MoveToNextElement());
ASSERT_EQ(reader->GetDepth(), 3);
ASSERT_EQ(reader->GetType(), XML_NODE_CDATA);
ASSERT_TRUE(reader->HasValue());
ASSERT_EQ(reader->GetValue(), L"some <br/> data");
// Move to the ns:objB_2 element ending node.
ASSERT_TRUE(reader->MoveToNextElement());
ASSERT_EQ(reader->GetDepth(), 2);
ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_END);
ASSERT_EQ(reader->GetLocalName(), L"objB_2");
ASSERT_EQ(reader->GetPrefix(), L"ns");
ASSERT_EQ(reader->GetQualifiedName(), L"ns:objB_2");
ASSERT_EQ(reader->GetNamespaceURI(), L"http://www.example.org/ns");
ASSERT_FALSE(reader->IsEmptyElement());
ASSERT_FALSE(reader->HasAttributes());
ASSERT_FALSE(reader->HasValue());
// Move to the whitespace node.
ASSERT_TRUE(reader->MoveToNextElement());
ASSERT_EQ(reader->GetType(), XML_NODE_WHITESPACE);
// Move to the ns:objB_3 element start node.
ASSERT_TRUE(reader->MoveToNextElement());
ASSERT_EQ(reader->GetDepth(), 2);
ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_START);
ASSERT_EQ(reader->GetLocalName(), L"objB_3");
ASSERT_EQ(reader->GetPrefix(), L"ns");
ASSERT_EQ(reader->GetQualifiedName(), L"ns:objB_3");
ASSERT_EQ(reader->GetNamespaceURI(), L"http://www.example.org/ns");
ASSERT_FALSE(reader->IsEmptyElement());
ASSERT_FALSE(reader->HasAttributes());
ASSERT_FALSE(reader->HasValue());
// Move to the EB entity reference node.
ASSERT_TRUE(reader->MoveToNextElement());
ASSERT_EQ(reader->GetDepth(), 3);
ASSERT_EQ(reader->GetType(), XML_NODE_ENTITY_REFERENCE);
ASSERT_EQ(reader->GetLocalName(), L"EB");
ASSERT_EQ(reader->GetQualifiedName(), L"EB");
ASSERT_TRUE(reader->HasValue());
ASSERT_EQ(reader->GetValue(), L"EB Value");
// Move to the ns:objB_3 element ending node.
ASSERT_TRUE(reader->MoveToNextElement());
ASSERT_EQ(reader->GetDepth(), 2);
ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_END);
ASSERT_EQ(reader->GetLocalName(), L"objB_3");
ASSERT_EQ(reader->GetPrefix(), L"ns");
ASSERT_EQ(reader->GetQualifiedName(), L"ns:objB_3");
ASSERT_EQ(reader->GetNamespaceURI(), L"http://www.example.org/ns");
ASSERT_FALSE(reader->IsEmptyElement());
ASSERT_FALSE(reader->HasAttributes());
ASSERT_FALSE(reader->HasValue());
// Move to the whitespace node.
ASSERT_TRUE(reader->MoveToNextElement());
ASSERT_EQ(reader->GetType(), XML_NODE_WHITESPACE);
// Move to the ns:objB_4 element start node.
ASSERT_TRUE(reader->MoveToNextElement());
ASSERT_EQ(reader->GetDepth(), 2);
ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_START);
ASSERT_EQ(reader->GetLocalName(), L"objB_4");
ASSERT_EQ(reader->GetPrefix(), L"ns");
ASSERT_EQ(reader->GetQualifiedName(), L"ns:objB_4");
ASSERT_EQ(reader->GetNamespaceURI(), L"http://www.example.org/ns");
ASSERT_FALSE(reader->IsEmptyElement());
ASSERT_FALSE(reader->HasAttributes());
ASSERT_FALSE(reader->HasValue());
ASSERT_EQ(reader->GetInnerXml(), L"<b>this is</b> mixed content &EA;");
ASSERT_EQ(reader->GetOuterXml(),
L"<ns:objB_4 xmlns:ns=\"http://www.example.org/ns\">"
L"<b>this is</b> mixed content &EA;</ns:objB_4>");
// Move to the <b> element node.
ASSERT_TRUE(reader->MoveToNextElement());
ASSERT_EQ(reader->GetDepth(), 3);
ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_START);
ASSERT_EQ(reader->GetLocalName(), L"b");
ASSERT_EQ(reader->GetQualifiedName(), L"b");
ASSERT_FALSE(reader->IsEmptyElement());
ASSERT_FALSE(reader->HasAttributes());
ASSERT_FALSE(reader->HasValue());
// Move to the text node.
ASSERT_TRUE(reader->MoveToNextElement());
ASSERT_EQ(reader->GetDepth(), 4);
ASSERT_EQ(reader->GetType(), XML_NODE_TEXT);
ASSERT_EQ(reader->GetLocalName(), L"#text");
ASSERT_EQ(reader->GetQualifiedName(), L"#text");
ASSERT_TRUE(reader->HasValue());
ASSERT_EQ(reader->GetValue(), L"this is");
// Move to the </b> element node.
ASSERT_TRUE(reader->MoveToNextElement());
ASSERT_EQ(reader->GetDepth(), 3);
ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_END);
ASSERT_EQ(reader->GetLocalName(), L"b");
ASSERT_EQ(reader->GetQualifiedName(), L"b");
// Move to the text node.
ASSERT_TRUE(reader->MoveToNextElement());
ASSERT_EQ(reader->GetDepth(), 3);
ASSERT_EQ(reader->GetType(), XML_NODE_TEXT);
ASSERT_EQ(reader->GetLocalName(), L"#text");
ASSERT_EQ(reader->GetQualifiedName(), L"#text");
ASSERT_TRUE(reader->HasValue());
ASSERT_EQ(reader->GetValue(), L" mixed content ");
// Move to the EA entity reference node.
ASSERT_TRUE(reader->MoveToNextElement());
ASSERT_EQ(reader->GetDepth(), 3);
ASSERT_EQ(reader->GetType(), XML_NODE_ENTITY_REFERENCE);
ASSERT_EQ(reader->GetLocalName(), L"EA");
ASSERT_EQ(reader->GetQualifiedName(), L"EA");
ASSERT_TRUE(reader->HasValue());
ASSERT_EQ(reader->GetValue(), L"EA Value");
// Move to the ns:objB_4 element ending node.
ASSERT_TRUE(reader->MoveToNextElement());
ASSERT_EQ(reader->GetDepth(), 2);
ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_END);
ASSERT_EQ(reader->GetLocalName(), L"objB_4");
ASSERT_EQ(reader->GetPrefix(), L"ns");
ASSERT_EQ(reader->GetQualifiedName(), L"ns:objB_4");
ASSERT_EQ(reader->GetNamespaceURI(), L"http://www.example.org/ns");
ASSERT_FALSE(reader->IsEmptyElement());
ASSERT_FALSE(reader->HasAttributes());
ASSERT_FALSE(reader->HasValue());
// Move to the whitespace node.
ASSERT_TRUE(reader->MoveToNextElement());
ASSERT_EQ(reader->GetType(), XML_NODE_WHITESPACE);
// Move to the ns:objB element ending node.
ASSERT_TRUE(reader->MoveToNextElement());
ASSERT_EQ(reader->GetDepth(), 1);
ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_END);
ASSERT_EQ(reader->GetLocalName(), L"objB");
ASSERT_EQ(reader->GetPrefix(), L"ns");
ASSERT_EQ(reader->GetQualifiedName(), L"ns:objB");
ASSERT_EQ(reader->GetNamespaceURI(), L"http://www.example.org/ns");
ASSERT_FALSE(reader->IsEmptyElement());
ASSERT_FALSE(reader->HasAttributes());
ASSERT_FALSE(reader->HasValue());
// Move to the whitespace node.
ASSERT_TRUE(reader->MoveToNextElement());
ASSERT_EQ(reader->GetType(), XML_NODE_WHITESPACE);
// Move to the ns:objC element start node.
ASSERT_TRUE(reader->MoveToNextElement());
ASSERT_EQ(reader->GetDepth(), 1);
ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_START);
ASSERT_EQ(reader->GetLocalName(), L"objC");
ASSERT_EQ(reader->GetPrefix(), L"ns");
ASSERT_EQ(reader->GetQualifiedName(), L"ns:objC");
ASSERT_EQ(reader->GetNamespaceURI(), L"http://www.example.org/ns");
ASSERT_TRUE(reader->IsEmptyElement());
ASSERT_TRUE(reader->HasAttributes());
ASSERT_FALSE(reader->HasValue());
ASSERT_EQ(reader->GetAttributeCount(), 2);
ASSERT_EQ(reader->GetAttribute(0), L"value C1");
ASSERT_EQ(reader->GetAttribute(L"ns:attr1"), L"value C1");
ASSERT_EQ(reader->GetAttribute(L"attr1", L"http://www.example.org/ns"),
L"value C1");
ASSERT_EQ(reader->GetAttribute(1), L"value C2");
ASSERT_EQ(reader->GetAttribute(L"ns:attr2"), L"value C2");
ASSERT_EQ(reader->GetAttribute(L"attr2", L"http://www.example.org/ns"),
L"value C2");
// Move to the ns:attr1 attribute.
ASSERT_TRUE(reader->MoveToFirstAttribute());
ASSERT_EQ(reader->GetDepth(), 2);
ASSERT_EQ(reader->GetType(), XML_NODE_ATTRIBUTE);
ASSERT_EQ(reader->GetLocalName(), L"attr1");
ASSERT_EQ(reader->GetPrefix(), L"ns");
ASSERT_EQ(reader->GetQualifiedName(), L"ns:attr1");
ASSERT_EQ(reader->GetNamespaceURI(), L"http://www.example.org/ns");
ASSERT_TRUE(reader->HasValue());
ASSERT_FALSE(reader->IsEmptyElement());
ASSERT_FALSE(reader->HasAttributes());
ASSERT_EQ(reader->GetValue(), L"value C1");
// Move to the ns:attr2 attribute.
ASSERT_TRUE(reader->MoveToNextAttribute());
ASSERT_EQ(reader->GetDepth(), 2);
ASSERT_EQ(reader->GetType(), XML_NODE_ATTRIBUTE);
ASSERT_EQ(reader->GetLocalName(), L"attr2");
ASSERT_EQ(reader->GetPrefix(), L"ns");
ASSERT_EQ(reader->GetQualifiedName(), L"ns:attr2");
ASSERT_EQ(reader->GetNamespaceURI(), L"http://www.example.org/ns");
ASSERT_TRUE(reader->HasValue());
ASSERT_FALSE(reader->IsEmptyElement());
ASSERT_FALSE(reader->HasAttributes());
ASSERT_EQ(reader->GetValue(), L"value C2");
// No more attributes.
ASSERT_FALSE(reader->MoveToNextAttribute());
// Return to the ns:objC element start node.
ASSERT_TRUE(reader->MoveToCarryingElement());
ASSERT_EQ(reader->GetDepth(), 1);
ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_START);
ASSERT_EQ(reader->GetQualifiedName(), L"ns:objC");
// Move to the ns:attr1 attribute.
ASSERT_TRUE(reader->MoveToAttribute(0));
ASSERT_EQ(reader->GetDepth(), 2);
ASSERT_EQ(reader->GetType(), XML_NODE_ATTRIBUTE);
ASSERT_EQ(reader->GetLocalName(), L"attr1");
ASSERT_EQ(reader->GetPrefix(), L"ns");
ASSERT_EQ(reader->GetQualifiedName(), L"ns:attr1");
ASSERT_EQ(reader->GetNamespaceURI(), L"http://www.example.org/ns");
ASSERT_TRUE(reader->HasValue());
ASSERT_FALSE(reader->IsEmptyElement());
ASSERT_FALSE(reader->HasAttributes());
ASSERT_EQ(reader->GetValue(), L"value C1");
// Return to the ns:objC element start node.
ASSERT_TRUE(reader->MoveToCarryingElement());
ASSERT_EQ(reader->GetDepth(), 1);
ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_START);
ASSERT_EQ(reader->GetQualifiedName(), L"ns:objC");
// Move to the ns:attr2 attribute.
ASSERT_TRUE(reader->MoveToAttribute(L"ns:attr2"));
ASSERT_EQ(reader->GetDepth(), 2);
ASSERT_EQ(reader->GetType(), XML_NODE_ATTRIBUTE);
ASSERT_EQ(reader->GetLocalName(), L"attr2");
ASSERT_EQ(reader->GetPrefix(), L"ns");
ASSERT_EQ(reader->GetQualifiedName(), L"ns:attr2");
ASSERT_EQ(reader->GetNamespaceURI(), L"http://www.example.org/ns");
ASSERT_TRUE(reader->HasValue());
ASSERT_FALSE(reader->IsEmptyElement());
ASSERT_FALSE(reader->HasAttributes());
ASSERT_EQ(reader->GetValue(), L"value C2");
// Move to the ns:attr1 attribute without returning to the ns:objC element.
ASSERT_TRUE(reader->MoveToAttribute(L"attr1", L"http://www.example.org/ns"));
ASSERT_EQ(reader->GetDepth(), 2);
ASSERT_EQ(reader->GetType(), XML_NODE_ATTRIBUTE);
ASSERT_EQ(reader->GetLocalName(), L"attr1");
ASSERT_EQ(reader->GetPrefix(), L"ns");
ASSERT_EQ(reader->GetQualifiedName(), L"ns:attr1");
ASSERT_EQ(reader->GetNamespaceURI(), L"http://www.example.org/ns");
ASSERT_TRUE(reader->HasValue());
ASSERT_FALSE(reader->IsEmptyElement());
ASSERT_FALSE(reader->HasAttributes());
ASSERT_EQ(reader->GetValue(), L"value C1");
// Move to the ns:objD element start node.
ASSERT_TRUE(reader->MoveToNextElement());
ASSERT_EQ(reader->GetDepth(), 1);
ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_START);
ASSERT_EQ(reader->GetLocalName(), L"objD");
ASSERT_EQ(reader->GetPrefix(), L"ns");
ASSERT_EQ(reader->GetQualifiedName(), L"ns:objD");
ASSERT_FALSE(reader->IsEmptyElement());
ASSERT_FALSE(reader->HasAttributes());
ASSERT_FALSE(reader->HasValue());
// Move to the ns:objD element end node.
ASSERT_TRUE(reader->MoveToNextElement());
ASSERT_EQ(reader->GetDepth(), 1);
ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_END);
ASSERT_EQ(reader->GetLocalName(), L"objD");
ASSERT_EQ(reader->GetPrefix(), L"ns");
ASSERT_EQ(reader->GetQualifiedName(), L"ns:objD");
ASSERT_FALSE(reader->IsEmptyElement());
ASSERT_FALSE(reader->HasAttributes());
ASSERT_FALSE(reader->HasValue());
// Move to the whitespace node without returning to the ns:objC element.
ASSERT_TRUE(reader->MoveToNextElement());
ASSERT_EQ(reader->GetType(), XML_NODE_WHITESPACE);
// Move to ns:obj element ending node.
ASSERT_TRUE(reader->MoveToNextElement());
ASSERT_EQ(reader->GetDepth(), 0);
ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_END);
ASSERT_EQ(reader->GetLocalName(), L"obj");
ASSERT_EQ(reader->GetPrefix(), L"ns");
ASSERT_EQ(reader->GetQualifiedName(), L"ns:obj");
ASSERT_EQ(reader->GetNamespaceURI(), L"http://www.example.org/ns");
ASSERT_FALSE(reader->IsEmptyElement());
ASSERT_TRUE(reader->HasAttributes());
ASSERT_FALSE(reader->HasValue());
// Strangely, the end node will report if the starting node has attributes
// but will not provide access to them.
ASSERT_TRUE(reader->HasAttributes());
ASSERT_EQ(reader->GetAttributeCount(), 0);
// And we're done.
ASSERT_FALSE(reader->MoveToNextElement());
ASSERT_TRUE(reader->Close());
}
// Test XML read error handling.
TEST(XmlReaderTest, ReadError)
{
char test_str[] =
"<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n"
"<!ATTRIBUTE foo bar>\n";
// Create the stream reader.
CefRefPtr<CefStreamReader> stream(
CefStreamReader::CreateForData(test_str, sizeof(test_str) - 1));
ASSERT_TRUE(stream.get() != NULL);
// Create the XML reader.
CefRefPtr<CefXmlReader> reader(
CefXmlReader::Create(stream, XML_ENCODING_NONE,
L"http://www.example.org/example.xml"));
ASSERT_TRUE(reader.get() != NULL);
// Move to the processing instruction node and generate parser error.
ASSERT_FALSE(reader->MoveToNextElement());
ASSERT_TRUE(reader->HasError());
}
// Test XmlObject load behavior.
TEST(XmlReaderTest, ObjectLoad)
{
// Create the stream reader.
CefRefPtr<CefStreamReader> stream(
CefStreamReader::CreateForData(g_test_xml, sizeof(g_test_xml) - 1));
ASSERT_TRUE(stream.get() != NULL);
// Create the XML reader.
CefRefPtr<CefXmlObject> object(new CefXmlObject(L"object"));
ASSERT_TRUE(object->Load(stream, XML_ENCODING_NONE,
L"http://www.example.org/example.xml", NULL));
ASSERT_FALSE(object->HasAttributes());
ASSERT_TRUE(object->HasChildren());
ASSERT_EQ(object->GetChildCount(), 1);
CefRefPtr<CefXmlObject> obj(object->FindChild(L"ns:obj"));
ASSERT_TRUE(obj.get());
ASSERT_TRUE(obj->HasChildren());
ASSERT_EQ(obj->GetChildCount(), 4);
CefRefPtr<CefXmlObject> obj_child(obj->FindChild(L"ns:objC"));
ASSERT_TRUE(obj_child.get());
ASSERT_EQ(obj_child->GetName(), L"ns:objC");
ASSERT_FALSE(obj_child->HasChildren());
ASSERT_FALSE(obj_child->HasValue());
ASSERT_TRUE(obj_child->HasAttributes());
CefXmlObject::ObjectVector obj_children;
ASSERT_EQ(obj->GetChildren(obj_children), 4);
ASSERT_EQ(obj_children.size(), 4);
CefXmlObject::ObjectVector::const_iterator it = obj_children.begin();
for (int ct = 0; it != obj_children.end(); ++it, ++ct) {
obj_child = *it;
ASSERT_TRUE(obj_child.get());
if (ct == 0) {
// ns:objA
ASSERT_EQ(obj_child->GetName(), L"ns:objA");
ASSERT_FALSE(obj_child->HasChildren());
ASSERT_TRUE(obj_child->HasValue());
ASSERT_FALSE(obj_child->HasAttributes());
ASSERT_EQ(obj_child->GetValue(), L"value A");
} else if (ct == 1) {
// ns:objB
ASSERT_EQ(obj_child->GetName(), L"ns:objB");
ASSERT_TRUE(obj_child->HasChildren());
ASSERT_FALSE(obj_child->HasValue());
ASSERT_FALSE(obj_child->HasAttributes());
ASSERT_EQ(obj_child->GetChildCount(), 4);
obj_child = obj_child->FindChild(L"ns:objB_4");
ASSERT_TRUE(obj_child.get());
ASSERT_TRUE(obj_child->HasValue());
ASSERT_EQ(obj_child->GetValue(),
L"<b>this is</b> mixed content EA Value");
} else if (ct == 2) {
// ns:objC
ASSERT_EQ(obj_child->GetName(), L"ns:objC");
ASSERT_FALSE(obj_child->HasChildren());
ASSERT_FALSE(obj_child->HasValue());
ASSERT_TRUE(obj_child->HasAttributes());
CefXmlObject::AttributeMap attribs;
ASSERT_EQ(obj_child->GetAttributes(attribs), 2);
ASSERT_EQ(attribs.size(), 2);
ASSERT_EQ(attribs[L"ns:attr1"], L"value C1");
ASSERT_EQ(attribs[L"ns:attr2"], L"value C2");
ASSERT_EQ(obj_child->GetAttributeCount(), 2);
ASSERT_TRUE(obj_child->HasAttribute(L"ns:attr1"));
ASSERT_EQ(obj_child->GetAttributeValue(L"ns:attr1"), L"value C1");
ASSERT_TRUE(obj_child->HasAttribute(L"ns:attr2"));
ASSERT_EQ(obj_child->GetAttributeValue(L"ns:attr2"), L"value C2");
} else if (ct == 3) {
// ns:objD
ASSERT_EQ(obj_child->GetName(), L"ns:objD");
ASSERT_FALSE(obj_child->HasChildren());
ASSERT_FALSE(obj_child->HasValue());
ASSERT_FALSE(obj_child->HasAttributes());
}
}
}
// Test XmlObject load error handling behavior.
TEST(XmlReaderTest, ObjectLoadError)
{
// Test start/end tag mismatch error.
{
char error_xml[] = "<obj>\n<foo>\n</obj>\n</foo>";
// Create the stream reader.
CefRefPtr<CefStreamReader> stream(
CefStreamReader::CreateForData(error_xml, sizeof(error_xml) - 1));
ASSERT_TRUE(stream.get() != NULL);
std::wstring error_str;
// Create the XML reader.
CefRefPtr<CefXmlObject> object(new CefXmlObject(L"object"));
ASSERT_FALSE(object->Load(stream, XML_ENCODING_NONE,
L"http://www.example.org/example.xml", &error_str));
ASSERT_EQ(error_str,
L"Opening and ending tag mismatch: foo line 2 and obj, line 3");
}
// Test value following child error.
{
char error_xml[] = "<obj>\n<foo>\n</foo>disallowed value\n</obj>";
// Create the stream reader.
CefRefPtr<CefStreamReader> stream(
CefStreamReader::CreateForData(error_xml, sizeof(error_xml) - 1));
ASSERT_TRUE(stream.get() != NULL);
std::wstring error_str;
// Create the XML reader.
CefRefPtr<CefXmlObject> object(new CefXmlObject(L"object"));
ASSERT_FALSE(object->Load(stream, XML_ENCODING_NONE,
L"http://www.example.org/example.xml", &error_str));
ASSERT_EQ(error_str,
L"Value following child element, line 4");
}
}