c++ - 有没有办法使用 libxml2 自动检测根标签中写入的命名空间?

标签 c++ xml xpath log4j libxml2

我正在尝试使用 libxml2 编写 XML 解析器(2.9.1 -> 我知道它很旧,但我现在无法更新它)。我使用的 XML 测试文件是 secret 文件,因此我无法与您分享。但是,在文件中我有以下行:

<?xml version="1.0"?>
<log4j:test xmlns:log4j="http://jakarta.apache.org/log4j/">

我的问题是关于 log4j 命名空间。使用 xmlParseFile 时,我假设它会被自动检测到但不会。我必须显式调用函数 xmlXPathRegisterNs。

所以我的问题是:有没有办法自动注册从文件中读取的命名空间?
在下面的代码中,我不想显式调用 xmlXPathRegisterNs。

感谢您的帮助。

PS:这是我的 beta 测试代码
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;                                                                                                                                                 
} 

最佳答案

实际上,您并不是在尝试编写 XML 解析器。 libxml2 是一个 XML 解析器。您正在尝试编写一个使用 XML 解析器的应用程序。

当您编写 XPath 表达式时,您可以将任何您喜欢的前缀绑定(bind)到您要查找的元素的 namespace 。您无需知道源文档中使用的前缀。

如果您不想注册 namespace 绑定(bind),那么您的 XPath 表达式不能使用任何 namespace 前缀,并且(假设这是 XPath 1.0)您将不得不使用循环 //*[local-name()='test']/*[local-name()='event']

关于c++ - 有没有办法使用 libxml2 自动检测根标签中写入的命名空间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60521025/

相关文章:

java - TextView 不在主屏幕上打印字符串

xml - XPATH帮助选择元素

selenium - 我可以使用 xpath 查找包含 "::after"的元素吗?

c++ - 如何在禁用异常的情况下检查构造函数的失败

c++ - 这个 void* 黑客攻击很糟糕吗?

css - 如何使用 XSL 在 XML 中的特定 td 中保留新行和空格

python - 有人可以解释一下如何在 python 上为 selenium 编写 xpath 吗?

c++ - 里面注入(inject)的DLL在哪里循环?

c++ - 在 mingw 中执行时禁用线程

xml - F# XML 类型提供程序和可选类型