void GameCore::ApplyAliases(tinyxml2::XMLElement *Source) { if (aliases.empty()) { return; } const tinyxml2::XMLAttribute *attr = Source->FirstAttribute(); while (attr != nullptr) { // Is the attribute value the same as an alias? If so, replace with alias' value if (aliases.find(UString(attr->Value())) != aliases.end()) { LogInfo("%s attribute \"%s\" value \"%s\" matches alias \"%s\"", Source->Name(), attr->Name(), attr->Value(), aliases[UString(attr->Value())].c_str()); Source->SetAttribute(attr->Name(), aliases[UString(attr->Value())].c_str()); } attr = attr->Next(); } // Replace inner text if (Source->GetText() != nullptr && aliases.find(UString(Source->GetText())) != aliases.end()) { LogInfo("%s value \"%s\" matches alias \"%s\"", Source->Name(), Source->GetText(), aliases[UString(Source->GetText())].c_str()); Source->SetText(aliases[UString(Source->GetText())].c_str()); } // Recurse down tree tinyxml2::XMLElement *child = Source->FirstChildElement(); while (child != nullptr) { ApplyAliases(child); child = child->NextSiblingElement(); } }
void GameCore::ParseXMLDoc(UString XMLFilename) { TRACE_FN_ARGS1("XMLFilename", XMLFilename); tinyxml2::XMLDocument doc; tinyxml2::XMLElement *node; auto file = fw().data->fs.open(XMLFilename); if (!file) { LogError("Failed to open XML file \"%s\"", XMLFilename.c_str()); } LogInfo("Loading XML file \"%s\" - found at \"%s\"", XMLFilename.c_str(), file.systemPath().c_str()); auto xmlText = file.readAll(); if (!xmlText) { LogError("Failed to read in XML file \"%s\"", XMLFilename.c_str()); } auto err = doc.Parse(xmlText.get(), file.size()); if (err != tinyxml2::XML_SUCCESS) { LogError("Failed to parse XML file \"%s\" - \"%s\" \"%s\"", XMLFilename.c_str(), doc.GetErrorStr1(), doc.GetErrorStr2()); return; } node = doc.RootElement(); if (!node) { LogError("Failed to parse XML file \"%s\" - no root element", XMLFilename.c_str()); return; } UString nodename = node->Name(); if (nodename == "openapoc") { for (node = node->FirstChildElement(); node != nullptr; node = node->NextSiblingElement()) { ApplyAliases(node); nodename = node->Name(); if (nodename == "game") { ParseGameXML(node); } else if (nodename == "form") { ParseFormXML(node); } else if (nodename == "apocfont") { UString fontName = node->Attribute("name"); if (fontName == "") { LogError("apocfont element with no name"); continue; } auto font = ApocalypseFont::loadFont(node); if (!font) { LogError("apocfont element \"%s\" failed to load", fontName.c_str()); continue; } if (this->fonts.find(fontName) != this->fonts.end()) { LogError("multiple fonts with name \"%s\"", fontName.c_str()); continue; } this->fonts[fontName] = font; } else if (nodename == "alias") { aliases[UString(node->Attribute("id"))] = UString(node->GetText()); } else if (nodename == "ufopaedia") { tinyxml2::XMLElement *nodeufo; for (nodeufo = node->FirstChildElement(); nodeufo != nullptr; nodeufo = nodeufo->NextSiblingElement()) { nodename = nodeufo->Name(); if (nodename == "category") { Ufopaedia::UfopaediaDB.push_back(mksp<UfopaediaCategory>(nodeufo)); } } } else { LogError("Unknown XML element \"%s\"", nodename.c_str()); } } } }
void GameCore::ParseXMLDoc(UString XMLFilename) { tinyxml2::XMLDocument doc; tinyxml2::XMLElement *node; UString systemPath; { auto file = fw.data->load_file(XMLFilename); if (!file) { LogError("Failed to open XML file \"%s\"", XMLFilename.c_str()); } systemPath = file.systemPath(); } if (systemPath == "") { LogError("Failed to read XML file \"%s\"", XMLFilename.c_str()); return; } LogInfo("Loading XML file \"%s\" - found at \"%s\"", XMLFilename.c_str(), systemPath.c_str()); doc.LoadFile(systemPath.c_str()); node = doc.RootElement(); if (!node) { LogError("Failed to parse XML file \"%s\"", systemPath.c_str()); return; } UString nodename = node->Name(); if (nodename == "openapoc") { for (node = node->FirstChildElement(); node != nullptr; node = node->NextSiblingElement()) { ApplyAliases(node); nodename = node->Name(); if (nodename == "game") { ParseGameXML(node); } else if (nodename == "string") { ParseStringXML(node); } else if (nodename == "form") { ParseFormXML(node); } else if (nodename == "apocfont") { UString fontName = node->Attribute("name"); if (fontName == "") { LogError("apocfont element with no name"); continue; } auto font = ApocalypseFont::loadFont(fw, node); if (!font) { LogError("apocfont element \"%s\" failed to load", fontName.c_str()); continue; } if (this->fonts.find(fontName) != this->fonts.end()) { LogError("multiple fonts with name \"%s\"", fontName.c_str()); continue; } this->fonts[fontName] = font; } else if (nodename == "language") { supportedlanguages[node->Attribute("id")] = node->GetText(); } else if (nodename == "alias") { aliases[UString(node->Attribute("id"))] = UString(node->GetText()); } else if (nodename == "ufopaedia") { tinyxml2::XMLElement *nodeufo; for (nodeufo = node->FirstChildElement(); nodeufo != nullptr; nodeufo = nodeufo->NextSiblingElement()) { nodename = nodeufo->Name(); if (nodename == "category") { Ufopaedia::UfopaediaDB.push_back( std::make_shared<UfopaediaCategory>(fw, nodeufo)); } } } else { LogError("Unknown XML element \"%s\"", nodename.c_str()); } } } }