bool Load()

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;
  }