Я пытаюсь написать синтаксический анализатор XML, используя libxml2 (2.9.1 -> Я знаю, что он старый, но я не могу сейчас его обновить). Используемый мной тестовый файл XML является конфиденциальным, поэтому я не могу поделиться им с вами. Но внутри файла у меня есть следующая строка:
<?xml version="1.0"?>
<log4j:test xmlns:log4j="http://jakarta.apache.org/log4j/">
Моя проблема связана с пространством имен log4j. При использовании xmlParseFile я предполагал, что он будет обнаружен автоматически, но нет. Я должен явно вызвать функцию xmlXPathRegisterNs.
Итак, мой вопрос: есть ли способ автоматически зарегистрировать пространства имен, считанные из файла? В приведенном ниже коде я не хочу явно вызывать xmlXPathRegisterNs.
Спасибо за вашу помощь.
PS: Вот мой код бета-теста
int main() {
std::string inputFilename = "myfile.xml";
xmlDocPtr document = xmlParseFile(inputFilename.c_str());
if (document == nullptr) {
std::cerr << "Document not parsed successfully" << std::endl;
return -1;
}
xmlXPathContextPtr context = xmlXPathNewContext(document);
if (context == nullptr) {
std::cerr << "Error in xmlXPathNewContext" << std::endl;
return -1;
}
if (xmlXPathRegisterNs(context, BAD_CAST "log4j", BAD_CAST "http://jakarta.apache.org/log4j/") != 0) {
std::cerr << "Unable to register namespace" << std::endl;
return -1;
}
xmlChar *xpath = (xmlChar*) "//log4j:test/log4j:event";
xmlXPathObjectPtr nodesList = xmlXPathEvalExpression(xpath, context);
if (nodesList == nullptr) {
std::cerr << "Error in xmlXPathEvalExpression" << std::endl;
return -1;
}
if (xmlXPathNodeSetIsEmpty(nodesList->nodesetval)) {
std::cerr << "No result found for //log4j:test/log4j:event" << std::endl;
return -1;
} else {
xmlNodeSetPtr nodeset = nodesList->nodesetval;
for (int i{0}; i < nodeset->nodeNr; i++) {
xmlChar *keyword = xmlNodeListGetString(document, nodeset->nodeTab[i]->xmlChildrenNode, 1);
std::cout << "Keyword: " << nodeset->nodeTab[i]->name << std::endl;
xmlFree(keyword);
}
xmlXPathFreeObject(nodesList);
}
xmlFreeDoc(document);
xmlCleanupParser();
return 0;
}