void CL_ResourceManager::load(CL_IODevice file, CL_VirtualDirectory directory) { CL_DomDocument new_document; new_document.load(file); // Check if loaded document uses namespaces and if its a clanlib resources xml document: CL_DomElement doc_element = new_document.get_document_element(); if (doc_element.get_namespace_uri().empty() && doc_element.get_local_name() == "resources") { impl->ns_resources = CL_String(); } else if (doc_element.get_namespace_uri() == "http://clanlib.org/xmlns/resources-1.0") { if (doc_element.get_local_name() != "resources") throw CL_Exception("ClanLib resource documents must begin with a resources element."); impl->ns_resources = "http://clanlib.org/xmlns/resources-1.0"; } else { throw CL_Exception("XML document is not a ClanLib resources document."); } impl->document = new_document; impl->directory = directory; impl->resources.clear(); std::vector<CL_String> section_stack; std::vector<CL_DomNode> nodes_stack; section_stack.push_back(CL_String()); nodes_stack.push_back(doc_element.get_first_child()); while (!nodes_stack.empty()) { if (nodes_stack.back().is_element()) { CL_DomElement element = nodes_stack.back().to_element(); if (element.get_namespace_uri() == impl->ns_resources && element.get_local_name() == "section") { CL_String section_name = element.get_attribute_ns(impl->ns_resources, "name"); section_stack.push_back(section_stack.back() + CL_PathHelp::add_trailing_slash(section_name, CL_PathHelp::path_type_virtual)); nodes_stack.push_back(element.get_first_child()); continue; } else if (element.has_attribute_ns(impl->ns_resources, "name")) { CL_String resource_name = element.get_attribute_ns(impl->ns_resources, "name"); CL_String resource_id = section_stack.back() + resource_name; impl->resources[resource_id] = CL_Resource(element, *this); } } nodes_stack.back() = nodes_stack.back().get_next_sibling(); while (nodes_stack.back().is_null()) { nodes_stack.pop_back(); section_stack.pop_back(); if (nodes_stack.empty()) break; nodes_stack.back() = nodes_stack.back().get_next_sibling(); } } }
CL_Resource CL_ResourceManager::create_resource(const CL_String &resource_id, const CL_String &type) { if (resource_exists(resource_id)) throw CL_Exception(cl_format("Resource %1 already exists", resource_id)); std::vector<CL_String> path_elements = CL_PathHelp::split_basepath(resource_id); CL_String name = CL_PathHelp::get_filename(resource_id); // Walk tree as deep as we can get: CL_DomNode parent = impl->document.get_document_element(); CL_DomNode cur = parent.get_first_child(); std::vector<CL_String>::iterator path_it = path_elements.begin(); while (!cur.is_null() && path_it != path_elements.end()) { if (cur.is_element() && cur.get_namespace_uri() == impl->ns_resources && cur.get_local_name() == "section") { CL_DomElement element = cur.to_element(); CL_String name = element.get_attribute_ns(impl->ns_resources, "name"); if (name == *path_it) { ++path_it; parent = cur; cur = cur.get_first_child(); continue; } } cur = cur.get_next_sibling(); } // Create any missing parent nodes: CL_String prefix = parent.get_prefix(); while (path_it != path_elements.end()) { CL_DomElement section; if (prefix.empty()) { section = impl->document.create_element_ns( impl->ns_resources, (*path_it) ); } else { section = impl->document.create_element_ns( impl->ns_resources,(prefix + ":" + *path_it)); } parent.append_child(section); parent = section; ++path_it; } // Create node: CL_DomElement resource_node; if (prefix.empty()) { resource_node = impl->document.create_element_ns( impl->ns_resources, (type)); } else { resource_node = impl->document.create_element_ns( impl->ns_resources,(prefix + ":" + type)); } resource_node.set_attribute_ns( impl->ns_resources, prefix.empty() ? "name" : (prefix + ":name"), name); parent.append_child(resource_node); // Create resource: impl->resources[resource_id] = CL_Resource(resource_node, *this); return impl->resources[resource_id]; }