in libcef_dll/wrapper/cef_xml_object.cc [20:147]
bool Load(CefRefPtr<CefStreamReader> stream,
CefXmlReader::EncodingType encodingType,
const CefString& URI) {
CefRefPtr<CefXmlReader> reader(
CefXmlReader::Create(stream, encodingType, URI));
if (!reader.get())
return false;
bool ret = reader->MoveToNextNode();
if (ret) {
CefRefPtr<CefXmlObject> cur_object(root_object_), new_object;
CefXmlObject::ObjectVector queue;
int cur_depth, value_depth = -1;
CefXmlReader::NodeType cur_type;
std::stringstream 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 << std::string(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 << std::string(reader->GetOuterXml());
} else {
// Value following a child element is not allowed.
std::stringstream ss;
ss << "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("");
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::stringstream ss;
ss << "Mismatched end tag for "
<< std::string(cur_object->GetName()) << ", 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 << std::string(reader->GetValue());
} else if (!cur_object->HasChildren()) {
// Start a new value.
value_depth = cur_depth;
cur_value << std::string(reader->GetValue());
} else {
// Value following a child element is not allowed.
std::stringstream ss;
ss << "Value following child element, line "
<< reader->GetLineNumber();
load_error_ = ss.str();
ret = false;
break;
}
}
} while (reader->MoveToNextNode());
}
if (reader->HasError()) {
load_error_ = reader->GetError();
return false;
}
return ret;
}