lxml xpath - Can't find body tag

Viewed 278

I'm trying to write a plugin in Calibre that checks for footnotes in an epub doc (basically looking for font-size < a certain value). I need to get all the child tags in a html file (inside the <body> tag) that contain text but I've come across a problem.

LXML xpath won't find the <body> or anything in it.

Below is the html which has been created from Calibre's own functions and an inserted <p>Hello World</p> using etree.SubElement

<?xml version='1.0' encoding='utf-8'?>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title>Hero filtered</title>
  <link href="page_styles.css" rel="stylesheet" type="text/css"/>
  <link href="stylesheet.css" rel="stylesheet" type="text/css"/>
</head>

<body>

<p>Hello World</p></body>
</html>

These are the things I've tried

query = ".//body" # This doesn't 
query = "body" # This doesn't 
query = ".//*/body" # This doesn't 
query = ".//*//body" # This doesn't
query = "./body" # This doesn't 
query = ".//body/*" # This doesn't 
query = ".//body/p" # This doesn't 

These do work though

query = "/*/*[2]/*[normalize-space(text())]" # this works
found= self.footnotes_file.find("{*}" + "body") # this works

I've been using the following function from lxml

found = self.footnotes_file.xpath(query)

where self.footnotes_file is generated with the Calibre function parsed(self, name) which returns the root element of the html file passed to it

self.footnotes_file = current_container().parsed(footnote_file_name)

So the question is what am I doing wrong!

1 Answers

You are running into problems with namespaces, it seems. There are a few ways to handle it. Two simple ones would be to delete the namespaces reference from

<html xmlns="http://www.w3.org/1999/xhtml">

so that the tag is just <html>.

Another is to change your query to

//*[local-name()="body"]

and see if these work.

Related