Search code examples
xmlc++11xpathlibxml2pugixml

XPath query does not work with pugixml


I'm curently porting a C++ project from libxml2 to pugixml. I have an XPath query that used to work perfectly well with libxml2 but returns zero nodes with pugixml:

"//*[local-name(.) = '" + name + "']"

where name is the name of the elements I want to retrieve. Can anyone shed any light on what's happening?

Code:

const string path = "//*[local-name(.) = '" + name + "']";
std::cerr << path << std::endl;
try {
   const xpath_node_set nodes = this->doc.select_nodes(path.c_str());
   return nodes;
} catch(const xpath_exception& e) {
   std::cerr << e.what() << std::endl;
   throw logic_error("Could not select elements from document.");
}

Name: "Page"

XML:

<MyDocument>
  <Pages>
    <Page>
      <Para>
        <Word>Some</Word>
        <Word>People</Word>
      </Para>
    </Page>
    <Page>
      <Para>
        <Word>Some</Word>
        <Word>Other</Word>
        <Word>People</Word>
      </Para>
    </Page>
  </Pages>
</MyDocument>

Solution

  • This program works for me. Are you using the latest version of pugixml?

    Alternatively I did notice that pugixml isn't good with namespaces, you may need to specify them in the node name you are searching for.

    I just checked and it works fine with namespaces.

    #include <pugixml.hpp>
    
    #include <iostream>
    
    const char* xml =
    "<MyDocument>"
    "  <Pages>"
    "    <Page>"
    "      <Para>"
    "        <Word>Some</Word>"
    "        <Word>People</Word>"
    "      </Para>"
    "    </Page>"
    "    <Page>"
    "      <Para>"
    "        <Word>Some</Word>"
    "        <Word>Other</Word>"
    "        <Word>People</Word>"
    "      </Para>"
    "    </Page>"
    "  </Pages>"
    "</MyDocument>";
    
    int main()
    {
        std::string name = "Para";
    
        const std::string path = "//*[local-name(.) = '" + name + "']";
    
        pugi::xml_parse_result result;
    
        pugi::xml_document doc;
    
        doc.load(xml);
    
        const pugi::xpath_node_set nodes = doc.select_nodes(path.c_str());
    
        for(auto& node: nodes)
        {
            std::cout << node.node().name() << '\n';
        }
    }
    

    OUTPUT

    Para
    Para